diff --git a/demos/scene.yaml b/demos/scene.yaml index 3e4ee06db..70cbdb879 100755 --- a/demos/scene.yaml +++ b/demos/scene.yaml @@ -1,3 +1,5 @@ +# include: transit.yaml + cameras: perspective: type: perspective diff --git a/demos/transit.yaml b/demos/transit.yaml new file mode 100644 index 000000000..01da1a0c3 --- /dev/null +++ b/demos/transit.yaml @@ -0,0 +1,31 @@ +layers: + transit: + data: { source: osm } + draw: + lines: + order: 49 + color: gray + width: 4px + outline: + color: black + width: 1px + interactive: true + + colored: + filter: { colour: true } + draw: + lines: + color: | + function() { + function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; + } + + var c = hexToRgb(feature.colour); + return [c.r/255, c.g/255, c.b/255]; + } diff --git a/src/gl/glsl.js b/src/gl/glsl.js index 8ba34334a..bfa7ad4aa 100644 --- a/src/gl/glsl.js +++ b/src/gl/glsl.js @@ -21,6 +21,7 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { var parsed = []; for (var name in uniforms) { + var key = name; // save the original name var uniform = uniforms[name]; var u; @@ -33,8 +34,10 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { parsed.push({ type: 'float', method: '1f', - name, value: - uniform + name, + value: uniform, + key, + uniforms }); } // Array: vector, array of floats, array of textures, or array of structs @@ -47,7 +50,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'vec' + uniform.length, method: uniform.length + 'fv', name, - value: uniform + value: uniform, + key, + uniforms }); } // float array @@ -56,7 +61,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'float[]', method: '1fv', name: name + '[0]', - value: uniform + value: uniform, + key, + uniforms }); } // TODO: assume matrix for (typeof == Float32Array && length == 16)? @@ -68,7 +75,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'sampler2D', method: '1i', name: name + '[' + u + ']', - value: uniform[u] + value: uniform[u], + key: u, + uniforms: uniform }); } } @@ -82,7 +91,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'vec' + uniform[0].length, method: uniform[u].length + 'fv', name: name + '[' + u + ']', - value: uniform[u] + value: uniform[u], + key: u, + uniforms: uniform }); } } @@ -102,7 +113,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'bool', method: '1i', name, - value: uniform + value: uniform, + key, + uniforms }); } // Texture @@ -111,7 +124,9 @@ GLSL.parseUniforms = function (uniforms, prefix = null) { type: 'sampler2D', method: '1i', name, - value: uniform + value: uniform, + key, + uniforms }); } // Structure diff --git a/src/scene.js b/src/scene.js index f0d7bce96..a0345df76 100755 --- a/src/scene.js +++ b/src/scene.js @@ -8,6 +8,7 @@ import Texture from './gl/texture'; import VertexArrayObject from './gl/vao'; import {StyleManager} from './styles/style_manager'; import {StyleParser} from './styles/style_parser'; +import SceneLoader from './scene_loader'; import Camera from './camera'; import Light from './light'; import TileManager from './tile_manager'; @@ -118,7 +119,7 @@ export default class Scene { // Load (or reload) scene config // Optionally specify new scene file URL - load(config_source = null) { + load(config_source = null, config_path = null) { if (this.initializing) { return Promise.resolve(); } @@ -128,7 +129,7 @@ export default class Scene { this.initializing = true; // Load scene definition (sources, styles, etc.), then create styles & workers - return this.loadScene(config_source) + return this.loadScene(config_source, config_path) .then(() => this.createWorkers()) .then(() => { this.createCanvas(); @@ -150,6 +151,7 @@ export default class Scene { this.initializing = false; this.initialized = true; this.last_valid_config_source = this.config_source; + this.last_valid_config_path = this.config_path; if (this.render_loop !== false) { this.setupRenderLoop(); @@ -174,7 +176,7 @@ export default class Scene { if (this.last_valid_config_source) { log.warn(message, error); log.info(`Scene.load() reverting to last valid configuration`); - return this.load(this.last_valid_config_source); + return this.load(this.last_valid_config_source, this.last_valid_config_path); } log.error(message, error); throw error; @@ -182,8 +184,8 @@ export default class Scene { } // For API compatibility - reload(config_source = null) { - return this.load(config_source); + reload(config_source = null, config_path = null) { + return this.load(config_source, config_path); } destroy() { @@ -930,26 +932,26 @@ export default class Scene { Load (or reload) the scene config @return {Promise} */ - loadScene(config_source = null) { + loadScene(config_source = null, config_path = null) { this.config_source = config_source || this.config_source; + if (typeof this.config_source === 'string') { - this.config_path = Utils.pathForURL(this.config_source); + this.config_path = config_path || Utils.pathForURL(this.config_source); } else { this.config_path = null; } - Texture.base_url = this.config_path; - return Utils.loadResource(this.config_source).then((config) => { + return SceneLoader.loadScene(this.config_source, this.config_path).then(config => { this.config = config; - return this.preProcessConfig().then(() => { this.trigger('load', { config: this.config }); }); + this.trigger('load', { config: this.config }); + return this.config; }); } loadDataSources() { for (var name in this.config.sources) { let source = this.config.sources[name]; - source.url = Utils.addBaseURL(source.url); this.sources[name] = DataSource.create(Object.assign({}, source, {name})); if (!this.sources[name]) { @@ -960,59 +962,11 @@ export default class Scene { } } - // Normalize some settings that may not have been explicitly specified in the scene definition - preProcessConfig() { - // Assign ids to data sources - let source_id = 0; - for (let source in this.config.sources) { - this.config.sources[source].id = source_id++; - } - - // If only one camera specified, set it as default - this.config.cameras = this.config.cameras || {}; - if (this.config.camera) { - this.config.cameras.default = this.config.camera; - } - let camera_names = Object.keys(this.config.cameras); - if (camera_names.length === 0) { - this.config.cameras.default = { active: true }; - - } - else if (!this._active_camera) { - // If no camera set as active, use first one - this.config.cameras[camera_names[0]].active = true; - } - - this.config.lights = this.config.lights || {}; // ensure lights object - this.config.styles = this.config.styles || {}; // ensure styles object - - return StyleManager.preload(this.config.styles, this.config_path); - } - // Load all textures in the scene definition loadTextures() { - this.normalizeTextures(); return Texture.createFromObject(this.gl, this.config.textures); } - // Handle single or multi-texture syntax, for stylesheet convenience - normalizeTextures() { - if (!this.config.styles) { - return; - } - - for (let [style_name, style] of Utils.entries(this.config.styles)) { - // If style has a single 'texture' object, move it to the global scene texture set - // and give it a default name - if (style.texture && typeof style.texture === 'object') { - let texture_name = '__' + style_name; - this.config.textures = this.config.textures || {}; - this.config.textures[texture_name] = style.texture; - style.texture = texture_name; // point stlye to location of texture - } - } - } - // Called (currently manually) after styles are updated in stylesheet updateStyles() { if (!this.initialized && !this.initializing) { diff --git a/src/scene_loader.js b/src/scene_loader.js new file mode 100644 index 000000000..0ef52760c --- /dev/null +++ b/src/scene_loader.js @@ -0,0 +1,168 @@ +import Utils from './utils/utils'; +import GLSL from './gl/glsl'; +// import {mergeObjects} from './styles/rule'; +import {StyleManager} from './styles/style_manager'; + +var SceneLoader; + +export default SceneLoader = { + + // Load scenes definitions from URL & proprocess + loadScene(url, path = null) { + return SceneLoader.loadSceneRecursive(url, path).then(SceneLoader.finalize); + }, + + // Loads scene files from URL, recursively loading 'included' scenes + // Optional *initial* path only (won't be passed to recursive 'include' calls) + // Useful for loading resources in base scene file from a separate location + // (e.g. in Tangram Play, when modified local scene should still refer to original resource URLs) + loadSceneRecursive(url, path = null) { + if (!url) { + return Promise.resolve({}); + } + + if (typeof url === 'string') { + path = path || Utils.pathForURL(url); + } + + return Utils.loadResource(url).then(config => { + return StyleManager.loadRemoteStyles(config.styles, path). + then(styles => StyleManager.loadShaderBlocks(styles, path)). // TODO: deprecate remote shader blocks? + then(() => { + // accept single-string or array + // if (typeof config.include === 'string') { + // config.include = [config.include]; + // } + + // if (!Array.isArray(config.include)) { + SceneLoader.normalize(config, path); + return config; + // } + + // Collect URLs of scenes to include + // let includes = []; + // for (let url of config.include) { + // includes.push(Utils.addBaseURL(url, path)); + // } + // delete config.include; // don't want to merge this property + + // return Promise. + // all(includes.map(url => SceneLoader.loadSceneRecursive(url))). + // then(configs => { + // config = mergeObjects({}, ...configs, config); + // SceneLoader.normalize(config, path); + // return config; + // }); + }); + }); + }, + + // Normalize properties that should be adjust within each local scene file (usually by path) + normalize(config, path) { + SceneLoader.normalizeDataSources(config, path); + SceneLoader.normalizeTextures(config, path); + return config; + }, + + // Expand paths for data source + normalizeDataSources(config, path) { + config.sources = config.sources || {}; + + for (let source of Utils.values(config.sources)) { + source.url = Utils.addBaseURL(source.url, path); + } + + return config; + }, + + // Expand paths and centralize texture definitions for a scene object + normalizeTextures(config, path) { + config.textures = config.textures || {}; + + if (config.styles) { + for (let [style_name, style] of Utils.entries(config.styles)) { + if (style.texture) { + // Texture by URL, expand relative to scene file + if (typeof style.texture === 'string' && !config.textures[style.texture]) { + style.texture = Utils.addBaseURL(style.texture, path); + } + // Texture by object, move it to the global scene texture set and give it a default name + else if (typeof style.texture === 'object') { + let texture_name = '__' + style_name; + config.textures[texture_name] = style.texture; + style.texture = texture_name; // point style to location of texture + } + } + + // If style has texture uniforms, expand texture URLs relative to scene file + if (style.shaders && style.shaders.uniforms) { + for (let {type, value, key, uniforms} of GLSL.parseUniforms(style.shaders.uniforms)) { + if (type === 'sampler2D' && !config.textures[value]) { + uniforms[key] = Utils.addBaseURL(value, path); + } + } + } + + // If style has material, expand texture URLs relative to scene file + if (style.material) { + for (let prop of ['emission', 'ambient', 'diffuse', 'specular', 'normal']) { + if (style.material[prop] != null && + style.material[prop].texture && + !config.textures[style.material[prop].texture]) { + style.material[prop].texture = Utils.addBaseURL(style.material[prop].texture, path); + } + } + } + } + } + + // Add path to textures + if (config.textures) { + for (let texture of Utils.values(config.textures)) { + texture.url = Utils.addBaseURL(texture.url, path); + } + } + + return config; + }, + + // Normalize some scene-wide settings that apply to the final, merged scene + finalize(config) { + // Assign ids to data sources + let source_id = 0; + for (let source in config.sources) { + config.sources[source].id = source_id++; + } + + // If only one camera specified, set it as default + config.cameras = config.cameras || {}; + if (config.camera) { + config.cameras.default = config.camera; + } + + // If no cameras specified, create one + if (Object.keys(config.cameras).length === 0) { + config.cameras.default = {}; + } + + // If no camera set as active, use first one + let active = false; + for (let camera of Utils.values(config.cameras)) { + if (camera.active) { + active = true; + break; + } + } + + if (!active) { + config.cameras[Object.keys(config.cameras)[0]].active = true; + } + + // Ensure top-level properties + config.lights = config.lights || {}; + config.styles = config.styles || {}; + + return config; + } + +}; diff --git a/src/styles/style_manager.js b/src/styles/style_manager.js index 68cdac5c5..ec8985929 100755 --- a/src/styles/style_manager.js +++ b/src/styles/style_manager.js @@ -70,12 +70,6 @@ StyleManager.remove = function (name) { delete Styles[name]; }; -// Preloads network resources in the stylesheet (shaders, textures, etc.) -StyleManager.preload = function (styles, base) { - // First load remote styles, then load shader blocks from remote URLs - return StyleManager.loadRemoteStyles(styles, base).then(styles => StyleManager.loadShaderBlocks(styles, base)); -}; - // Load style definitions from external URLs StyleManager.loadRemoteStyles = function (styles, base) { // Collect URLs and modes to import from them @@ -128,14 +122,14 @@ StyleManager.loadRemoteStyles = function (styles, base) { } else { delete styles[target.target_name]; - return reject(new Error(`StyleManager.preload: error importing style ${target.target_name}, could not find source style ${target.source_name} in ${url}`)); + return reject(new Error(`StyleManager.loadRemoteStyles: error importing style ${target.target_name}, could not find source style ${target.source_name} in ${url}`)); } } resolve(); this.selection = false; }).catch((error) => { - log.error(`StyleManager.preload: error importing style(s) ${JSON.stringify(urls[url])} from ${url}`, error); + log.error(`StyleManager.loadRemoteStyles: error importing style(s) ${JSON.stringify(urls[url])} from ${url}`, error); }); }); })).then(() => Promise.resolve(styles)); @@ -143,6 +137,9 @@ StyleManager.loadRemoteStyles = function (styles, base) { // Preload shader blocks from external URLs StyleManager.loadShaderBlocks = function (styles, base) { + if (!styles) { + return Promise.resolve({}); + } var queue = []; for (var style of Utils.values(styles)) { if (style.shaders && style.shaders.blocks) { diff --git a/test/fixtures/sample-scene.json b/test/fixtures/sample-scene.json index 9218e44df..46627a633 100644 --- a/test/fixtures/sample-scene.json +++ b/test/fixtures/sample-scene.json @@ -1,118 +1,115 @@ { + "sources": { + "osm": { + "max_zoom": 20, + "type": "GeoJSON", + "url": "http://vector.mapzen.com/osm/all/{z}/{x}/{y}.json" + } + }, - "config": { - - "sources": { - "osm": { - "max_zoom": 20, - "type": "GeoJSONTiles", - "url": "http://vector.mapzen.com/osm/all/{z}/{x}/{y}.json" + "layers": { + "earth": { + "data": { + "source": "osm" + }, + "draw": { + "polygons": { + "color": [0.175, 0.175, 0.175], + "order": 0 + } } }, - - "layers": { - "earth": { - "data": { - "source": "osm" - }, - "draw": { - "polygons": { - "color": [0.175, 0.175, 0.175], - "order": 0 - } - } + "landuse": { + "data": { + "source": "osm" }, - "landuse": { - "data": { - "source": "osm" - }, - "draw": { - "polygons": { - "color": [0.5, 0.875, 0.5], - "order": 1 - } + "draw": { + "polygons": { + "color": [0.5, 0.875, 0.5], + "order": 1 } + } + }, + "water": { + "data": { + "source": "osm" }, - "water": { - "data": { - "source": "osm" - }, - "draw": { - "polygons": { - "color": [0.5, 0.5, 0.875], - "order": 2 - } + "draw": { + "polygons": { + "color": [0.5, 0.5, 0.875], + "order": 2 } + } + }, + "roads": { + "data": { + "source": "osm" }, - "roads": { - "data": { - "source": "osm" - }, - "draw": { - "lines": { - "color": [0.4, 0.4, 0.4], - "order": 3 - } + "draw": { + "lines": { + "color": [0.4, 0.4, 0.4], + "order": 3 } + } + }, + "buildings": { + "data": { + "source": "osm" }, - "buildings": { - "data": { - "source": "osm" - }, - "draw": { - "polygons": { - "style": "rainbow", - "color": [0.6, 0.6, 0.6], - "order": 4 - } + "draw": { + "polygons": { + "style": "rainbow", + "color": [0.6, 0.6, 0.6], + "order": 4 } } - }, - "lights": { - "ambient": { - "type": "ambient", - "ambient": 0.5 + } + }, + "lights": { + "ambient": { + "type": "ambient", + "ambient": 0.5 + } + }, + "styles": { + "rainbow_child": { + "mix": "rainbow", + "animated": true, + "shaders": { + "blocks": { + "color": + "color.rgb = clamp(hsv2rgb(c) * 2., 0., 1.);" + } } }, - "styles": { - "rainbow_child": { - "mix": "rainbow", - "animated": true, - "shaders": { - "blocks": { - "color": - "color.rgb = clamp(hsv2rgb(c) * 2., 0., 1.);" - } + "rainbow": { + "base": "polygons", + "animated": true, + "shaders": { + "blocks": { + "global": + "vec3 hsv2rgb(vec3 c) { \n\ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); \n\ + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); \n\ + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); \n\ + }", + "color": + "vec3 c = vec3(v_world_position.z * .003 + u_time / 10., 1.0, 1.0); \n\ + color.rgb = hsv2rgb(c);" } - }, - "rainbow": { - "base": "polygons", - "animated": true, - "shaders": { - "blocks": { - "global": - "vec3 hsv2rgb(vec3 c) { \n\ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); \n\ - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); \n\ - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); \n\ - }", - "color": - "vec3 c = vec3(v_world_position.z * .003 + u_time / 10., 1.0, 1.0); \n\ - color.rgb = hsv2rgb(c);" - } - } - }, - "scale": { - "base": "polygons", - "shaders": { - "uniforms": { - "scale": [1, 2, 3] - }, - "blocks": { - "position": - "position.xyz *= scale;" - } + } + }, + "scale": { + "base": "polygons", + "shaders": { + "uniforms": { + "scale": [1, 2, 3] + }, + "blocks": { + "position": + "position.xyz *= scale;" } } } - }} + } +} diff --git a/test/fixtures/sample-scene.yaml b/test/fixtures/sample-scene.yaml new file mode 100644 index 000000000..da16837bb --- /dev/null +++ b/test/fixtures/sample-scene.yaml @@ -0,0 +1,80 @@ +sources: + osm: + type: GeoJSON + url: http://vector.mapzen.com/osm/all/{z}/{x}/{y}.json + +layers: + earth: + data: { source: osm } + draw: + polygons: + order: 0 + color: [0.175, 0.175, 0.175] + + landuse: + data: { source: osm } + draw: + polygons: + order: 1 + color: [0.5, 0.875, 0.5] + + + water: + data: { source: osm } + draw: + polygons: + order: 2 + color: [0.5, 0.5, 0.875] + + roads: + data: { source: osm } + draw: + lines: + order: 3 + color: [0.4, 0.4, 0.4] + + + buildings: + data: { source: osm } + draw: + polygons: + order: 4 + style: rainbow + color: [0.6, 0.6, 0.6] + +lights: + ambient: + type: ambient + ambient: 0.5 + +styles: + rainbow_child: + mix: rainbow + shaders: + blocks: + color: + color.rgb = clamp(hsv2rgb(c) * 2., 0., 1.); + + rainbow: + base: polygons + animated: true + shaders: + blocks: + global: | + vec3 hsv2rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); + } + color: | + vec3 c = vec3(v_world_position.z * .003 + u_time / 10., 1.0, 1.0); + color.rgb = hsv2rgb(c); + + scale: + base: polygons + shaders: + uniforms: + scale: [1, 2, 3] + blocks: + position: + position.xyz *= scale; diff --git a/test/helpers.js b/test/helpers.js index a1f37b345..94a4f811f 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,5 +1,4 @@ import Scene from '../src/scene'; -import sampleScene from './fixtures/sample-scene'; /* Special web worker treatment: @@ -49,7 +48,7 @@ window.makeScene = function (options) { options.logLevel = options.logLevel || 'info'; return new Scene( - sampleScene.config, + options.config || 'http://localhost:9876/base/test/fixtures/sample-scene.yaml', options ); diff --git a/test/leaflet_layer_spec.js b/test/leaflet_layer_spec.js index 4911dcda2..b53305449 100644 --- a/test/leaflet_layer_spec.js +++ b/test/leaflet_layer_spec.js @@ -12,8 +12,7 @@ map.setView([0, 0], 0); // required to put leaflet in a "ready" state, or it wil let makeOne = () => { let layer = new LeafletLayer({ - source: sampleScene.tile_source, - scene: sampleScene.config, + scene: sampleScene, disableRenderLoop: true, workerUrl: 'http://localhost:9876/tangram.debug.js' }); diff --git a/test/scene_spec.js b/test/scene_spec.js index bcbf282d8..6621d59bb 100644 --- a/test/scene_spec.js +++ b/test/scene_spec.js @@ -27,14 +27,6 @@ describe('Scene', function () { assert.instanceOf(subject, Scene); }); - it('correctly sets the value of the layers object', () => { - assert.equal(subject.layer_source, sampleScene.layers); - }); - - it('correctly sets the value of the config object', () => { - assert.equal(subject.config_source, sampleScene.config); - }); - }); @@ -74,6 +66,23 @@ describe('Scene', function () { }); }); + describe('loading scene from an existing object', () => { + + beforeEach(() => { + subject = makeScene({ config: sampleScene }); + return subject.load(); + }); + + it('correctly sets the value of the config object', () => { + assert.equal(subject.config_source, sampleScene); + }); + + it('sets the initialized property', () => { + assert.isTrue(subject.initialized); + }); + + }); + describe('when the scene is already initialized', () => { it('handles second load() call', () => { diff --git a/test/style_spec.js b/test/style_spec.js index 1393fbfe3..5b1f6f4a4 100644 --- a/test/style_spec.js +++ b/test/style_spec.js @@ -40,7 +40,7 @@ describe('Styles:', () => { }); it('creates a custom style', () => { - StyleManager.create('rainbow', sampleScene.config.styles.rainbow); + StyleManager.create('rainbow', sampleScene.styles.rainbow); assert.equal(Styles.rainbow.constructor, Style.constructor); assert.equal(Styles.rainbow.base, 'polygons'); }); @@ -48,7 +48,7 @@ describe('Styles:', () => { describe('builds custom styles w/dependencies from stylesheet', () => { beforeEach(() => { - StyleManager.build(sampleScene.config.styles); + StyleManager.build(sampleScene.styles); }); it('compiles parent custom style', () => { @@ -73,14 +73,16 @@ describe('Styles:', () => { it('loads a remote style from a URL', (done) => { let styles = { windows: { url: 'http://localhost:9876/base/test/fixtures/sample-remote-style.yaml' } }; - StyleManager.preload(styles).then(() => { - StyleManager.build(styles); - Styles.windows.setGL(gl); - Styles.windows.compile(); - assert.ok(Styles.windows.compiled); - assert.ok(Styles.windows.program.compiled); - done(); - }); + StyleManager.loadRemoteStyles(styles) + .then(styles => StyleManager.loadShaderBlocks(styles)) + .then(() => { + StyleManager.build(styles); + Styles.windows.setGL(gl); + Styles.windows.compile(); + assert.ok(Styles.windows.compiled); + assert.ok(Styles.windows.program.compiled); + done(); + }); }); it('loads a remote style from a URL, with a different local name', (done) => { @@ -88,14 +90,16 @@ describe('Styles:', () => { name: 'windows', url: 'http://localhost:9876/base/test/fixtures/sample-remote-style.yaml' } }; - StyleManager.preload(styles).then(() => { - StyleManager.build(styles); - Styles.localName.setGL(gl); - Styles.localName.compile(); - assert.ok(Styles.localName.compiled); - assert.ok(Styles.localName.program.compiled); - done(); - }); + StyleManager.loadRemoteStyles(styles) + .then(styles => StyleManager.loadShaderBlocks(styles)) + .then(() => { + StyleManager.build(styles); + Styles.localName.setGL(gl); + Styles.localName.compile(); + assert.ok(Styles.localName.compiled); + assert.ok(Styles.localName.program.compiled); + done(); + }); }); }); @@ -122,7 +126,7 @@ describe('Styles:', () => { }); it('injects a dependent uniform in a custom style', () => { - StyleManager.create('scale', sampleScene.config.styles.scale); + StyleManager.create('scale', sampleScene.styles.scale); Styles.scale.init(); Styles.scale.setGL(gl); Styles.scale.compile();