Skip to content

Commit

Permalink
Merge pull request #412 from tangrams/reapply-globals
Browse files Browse the repository at this point in the history
Re-apply global property substitution
  • Loading branch information
bcamper authored Sep 19, 2016
2 parents 5e697a8 + 7864387 commit 34a897a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ export default class Scene {
*/
loadScene(config_source = null, config_path = null) {
this.config_source = config_source || this.config_source;
this.config_globals_applied = [];

if (typeof this.config_source === 'string') {
this.config_path = Utils.pathForURL(config_path || this.config_source);
Expand Down Expand Up @@ -979,6 +980,7 @@ export default class Scene {
this.generation = ++Scene.generation;
this.updating++;

this.config = SceneLoader.applyGlobalProperties(this.config, this.config_globals_applied);
this.style_manager.init();
this.view.reset();
this.createLights();
Expand Down
46 changes: 24 additions & 22 deletions src/scene_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,26 +177,44 @@ export default SceneLoader = {
// Substitutes global scene properties (those defined in the `config.global` object) for any style values
// of the form `global.`, for example `color: global.park_color` would be replaced with the value (if any)
// defined for the `park_color` property in `config.global.park_color`.
applyGlobalProperties(config) {
applyGlobalProperties(config, applied) {
if (!config.global || Object.keys(config.global).length === 0) {
return config; // no global properties to transform
}

// Parse properties from globals
const separator = ':';
const props = flattenProperties(config.global, separator);

function applyProps (obj) {
// Re-apply previously applied properties
// NB: a current shortcoming here is that you cannot "un-link" a target property from a global
// at run-time. Once a global property substitution has been recorderd, it will always be re-applied
// on subsequent scene updates, even if the target property was updated to another literal value.
// This is unlikely to be a common occurrence an acceptable limitation for now.
applied.forEach(({ prop, target, key }) => {
if (target && props[prop]) {
target[key] = props[prop];
// log('info', `Re-applying ${prop} with value ${props[prop]} to key ${key} in`, target);
}
});

// Find and apply new properties
function applyProps (obj, target, key) {
// Convert string
if (typeof obj === 'string') {
let key = (obj.slice(0, 7) === 'global.') && (obj.slice(7).replace(/\./g, separator));
if (key && props[key] !== undefined) {
obj = props[key];
const prop = (obj.slice(0, 7) === 'global.') && (obj.slice(7).replace(/\./g, separator));
if (prop && props[prop] !== undefined) {
// Save record of where property is applied
applied.push({ prop, target, key });

// Apply property
obj = props[prop];
}
}
// Loop through object properties
else if (typeof obj === 'object') {
for (let p in obj) {
obj[p] = applyProps(obj[p]);
obj[p] = applyProps(obj[p], obj, p);
}
}
return obj;
Expand All @@ -218,9 +236,6 @@ export default SceneLoader = {
config.styles = config.styles || {};
config.layers = config.layers || {};

// Replace global scene properties
config = this.applyGlobalProperties(config);

// Assign ids to data sources
let source_id = 0;
for (let source in config.sources) {
Expand All @@ -237,19 +252,6 @@ export default SceneLoader = {
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;
}

// If no lights specified, create default
if (Object.keys(config.lights).length === 0 ||
Object.keys(config.lights).every(i => config.lights[i].visible === false)) {
Expand Down
4 changes: 4 additions & 0 deletions src/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export default class View {
return name;
}
}

// If no camera set as active, use first one
let keys = Object.keys(this.scene.config.cameras);
return keys.length && keys[0];
}
}

Expand Down

0 comments on commit 34a897a

Please sign in to comment.