mirror of
https://github.com/beestat/app.git
synced 2026-02-26 05:00:21 -05:00
Cleanup Refactor 1
This commit is contained in:
parent
236bf6caa5
commit
5c33d96d1d
@ -13,23 +13,6 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
|
||||
beestat.setting('visualize.floor_plan_id')
|
||||
).x === Infinity;
|
||||
|
||||
/* const change_function = beestat.debounce(function() {
|
||||
// todo replace these with (if entity set active false?)
|
||||
delete self.state_.active_group;
|
||||
|
||||
self.rerender();
|
||||
|
||||
// Center the content if the floor plan changed.
|
||||
if (self.floor_plan_ !== undefined) {
|
||||
self.floor_plan_.center_content();
|
||||
}
|
||||
}, 10);
|
||||
|
||||
beestat.dispatcher.addEventListener(
|
||||
'setting.visualize.floor_plan_id',
|
||||
change_function
|
||||
);*/
|
||||
|
||||
beestat.component.card.apply(this, arguments);
|
||||
|
||||
// Snapping initial
|
||||
@ -58,6 +41,39 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
|
||||
};
|
||||
beestat.extend(beestat.component.card.floor_plan_editor, beestat.component.card);
|
||||
|
||||
beestat.component.card.floor_plan_editor.layer_type_meta_ = {
|
||||
'rooms': {
|
||||
'active_state_key': 'active_room_entity',
|
||||
'id_key': 'room_id',
|
||||
'getter_name': 'get_room',
|
||||
'clears_geometry_selection': true
|
||||
},
|
||||
'surfaces': {
|
||||
'active_state_key': 'active_surface_entity',
|
||||
'id_key': 'surface_id',
|
||||
'getter_name': 'get_surface',
|
||||
'clears_geometry_selection': true
|
||||
},
|
||||
'openings': {
|
||||
'active_state_key': 'active_opening_entity',
|
||||
'id_key': 'opening_id',
|
||||
'getter_name': 'get_opening',
|
||||
'clears_geometry_selection': false
|
||||
},
|
||||
'trees': {
|
||||
'active_state_key': 'active_tree_entity',
|
||||
'id_key': 'tree_id',
|
||||
'getter_name': 'get_tree',
|
||||
'clears_geometry_selection': false
|
||||
},
|
||||
'light_sources': {
|
||||
'active_state_key': 'active_light_source_entity',
|
||||
'id_key': 'light_source_id',
|
||||
'getter_name': 'get_light_source',
|
||||
'clears_geometry_selection': false
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate.
|
||||
*
|
||||
@ -474,58 +490,28 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func
|
||||
self.floor_plan_.set_width(drawing_canvas_container.getBoundingClientRect().width);
|
||||
});
|
||||
|
||||
// Rerender when stuff happens
|
||||
this.floor_plan_.addEventListener('add_room', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_room', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_point', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('add_surface', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_surface', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('add_tree', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_tree', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('add_opening', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_opening', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('add_light_source', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('remove_light_source', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('undo', function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
});
|
||||
this.floor_plan_.addEventListener('redo', function() {
|
||||
// Rerender when floor-plan model changes.
|
||||
const rerender_events = [
|
||||
'add_room',
|
||||
'remove_room',
|
||||
'remove_point',
|
||||
'add_surface',
|
||||
'remove_surface',
|
||||
'add_tree',
|
||||
'remove_tree',
|
||||
'add_opening',
|
||||
'remove_opening',
|
||||
'add_light_source',
|
||||
'remove_light_source',
|
||||
'undo',
|
||||
'redo'
|
||||
];
|
||||
const handle_floor_plan_mutation = function() {
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
};
|
||||
rerender_events.forEach(function(event_name) {
|
||||
self.floor_plan_.addEventListener(event_name, handle_floor_plan_mutation);
|
||||
});
|
||||
this.floor_plan_.addEventListener('change_group', self.rerender.bind(this));
|
||||
|
||||
@ -887,48 +873,10 @@ beestat.component.card.floor_plan_editor.prototype.set_layer_object_visibility_
|
||||
object.editor_hidden = visible !== true;
|
||||
|
||||
if (visible !== true) {
|
||||
if (
|
||||
type === 'rooms' &&
|
||||
this.state_.active_room_entity !== undefined &&
|
||||
this.state_.active_room_entity.get_room().room_id === object_id
|
||||
) {
|
||||
this.state_.active_room_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'surfaces' &&
|
||||
this.state_.active_surface_entity !== undefined &&
|
||||
this.state_.active_surface_entity.get_surface().surface_id === object_id
|
||||
) {
|
||||
this.state_.active_surface_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'trees' &&
|
||||
this.state_.active_tree_entity !== undefined &&
|
||||
this.state_.active_tree_entity.get_tree().tree_id === object_id
|
||||
) {
|
||||
this.state_.active_tree_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'openings' &&
|
||||
this.state_.active_opening_entity !== undefined &&
|
||||
this.state_.active_opening_entity.get_opening().opening_id === object_id
|
||||
) {
|
||||
this.state_.active_opening_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'light_sources' &&
|
||||
this.state_.active_light_source_entity !== undefined &&
|
||||
this.state_.active_light_source_entity.get_light_source().light_source_id === object_id
|
||||
) {
|
||||
this.state_.active_light_source_entity.set_active(false);
|
||||
}
|
||||
this.deactivate_active_entity_for_layer_object_(type, object_id);
|
||||
}
|
||||
|
||||
this.floor_plan_.update_infobox();
|
||||
this.floor_plan_.update_toolbar();
|
||||
this.update_info_pane_();
|
||||
this.update_floor_plan_();
|
||||
this.rerender();
|
||||
this.sync_after_layer_change_();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -948,48 +896,10 @@ beestat.component.card.floor_plan_editor.prototype.set_layer_object_locked_ = fu
|
||||
object.editor_locked = locked;
|
||||
|
||||
if (locked === true) {
|
||||
if (
|
||||
type === 'rooms' &&
|
||||
this.state_.active_room_entity !== undefined &&
|
||||
this.state_.active_room_entity.get_room().room_id === object_id
|
||||
) {
|
||||
this.state_.active_room_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'surfaces' &&
|
||||
this.state_.active_surface_entity !== undefined &&
|
||||
this.state_.active_surface_entity.get_surface().surface_id === object_id
|
||||
) {
|
||||
this.state_.active_surface_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'trees' &&
|
||||
this.state_.active_tree_entity !== undefined &&
|
||||
this.state_.active_tree_entity.get_tree().tree_id === object_id
|
||||
) {
|
||||
this.state_.active_tree_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'openings' &&
|
||||
this.state_.active_opening_entity !== undefined &&
|
||||
this.state_.active_opening_entity.get_opening().opening_id === object_id
|
||||
) {
|
||||
this.state_.active_opening_entity.set_active(false);
|
||||
}
|
||||
if (
|
||||
type === 'light_sources' &&
|
||||
this.state_.active_light_source_entity !== undefined &&
|
||||
this.state_.active_light_source_entity.get_light_source().light_source_id === object_id
|
||||
) {
|
||||
this.state_.active_light_source_entity.set_active(false);
|
||||
}
|
||||
this.deactivate_active_entity_for_layer_object_(type, object_id);
|
||||
}
|
||||
|
||||
this.floor_plan_.update_infobox();
|
||||
this.floor_plan_.update_toolbar();
|
||||
this.update_info_pane_();
|
||||
this.update_floor_plan_();
|
||||
this.rerender();
|
||||
this.sync_after_layer_change_();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1039,7 +949,7 @@ beestat.component.card.floor_plan_editor.prototype.set_layer_visible_ = function
|
||||
* @param {boolean} locked
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.set_group_locked_ = function(group, locked) {
|
||||
['rooms', 'surfaces', 'openings', 'trees', 'light_sources'].forEach(function(type) {
|
||||
this.get_layer_types_().forEach(function(type) {
|
||||
const collection = group[type] || [];
|
||||
collection.forEach(function(object) {
|
||||
object.editor_locked = locked;
|
||||
@ -1047,11 +957,9 @@ beestat.component.card.floor_plan_editor.prototype.set_group_locked_ = function(
|
||||
});
|
||||
|
||||
if (locked === true) {
|
||||
this.deactivate_active_entity_for_group_type_(group, 'rooms');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'surfaces');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'openings');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'trees');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'light_sources');
|
||||
this.get_layer_types_().forEach(function(type) {
|
||||
this.deactivate_active_entity_for_group_type_(group, type);
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.sync_after_layer_change_();
|
||||
@ -1064,7 +972,7 @@ beestat.component.card.floor_plan_editor.prototype.set_group_locked_ = function(
|
||||
* @param {boolean} visible
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.set_group_visible_ = function(group, visible) {
|
||||
['rooms', 'surfaces', 'openings', 'trees', 'light_sources'].forEach(function(type) {
|
||||
this.get_layer_types_().forEach(function(type) {
|
||||
const collection = group[type] || [];
|
||||
collection.forEach(function(object) {
|
||||
object.editor_hidden = visible !== true;
|
||||
@ -1072,11 +980,9 @@ beestat.component.card.floor_plan_editor.prototype.set_group_visible_ = function
|
||||
});
|
||||
|
||||
if (visible !== true) {
|
||||
this.deactivate_active_entity_for_group_type_(group, 'rooms');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'surfaces');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'openings');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'trees');
|
||||
this.deactivate_active_entity_for_group_type_(group, 'light_sources');
|
||||
this.get_layer_types_().forEach(function(type) {
|
||||
this.deactivate_active_entity_for_group_type_(group, type);
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.sync_after_layer_change_();
|
||||
@ -1089,38 +995,13 @@ beestat.component.card.floor_plan_editor.prototype.set_group_visible_ = function
|
||||
* @param {string} type rooms|surfaces|openings|trees
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.deactivate_active_entity_for_group_type_ = function(group, type) {
|
||||
if (type === 'rooms' && this.state_.active_room_entity !== undefined) {
|
||||
if (this.state_.active_room_entity.group_ === group) {
|
||||
this.state_.active_room_entity.set_active(false);
|
||||
}
|
||||
const metadata = this.get_layer_type_meta_(type);
|
||||
if (metadata === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'surfaces' && this.state_.active_surface_entity !== undefined) {
|
||||
if (this.state_.active_surface_entity.group_ === group) {
|
||||
this.state_.active_surface_entity.set_active(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'trees' && this.state_.active_tree_entity !== undefined) {
|
||||
if (this.state_.active_tree_entity.group_ === group) {
|
||||
this.state_.active_tree_entity.set_active(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'openings' && this.state_.active_opening_entity !== undefined) {
|
||||
if (this.state_.active_opening_entity.group_ === group) {
|
||||
this.state_.active_opening_entity.set_active(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'light_sources' && this.state_.active_light_source_entity !== undefined) {
|
||||
if (this.state_.active_light_source_entity.group_ === group) {
|
||||
this.state_.active_light_source_entity.set_active(false);
|
||||
}
|
||||
const active_entity = this.state_[metadata.active_state_key];
|
||||
if (active_entity !== undefined && active_entity.group_ === group) {
|
||||
active_entity.set_active(false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1175,59 +1056,28 @@ beestat.component.card.floor_plan_editor.prototype.reorder_layer_object_ = funct
|
||||
* Ensure hidden active entities are cleared.
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.ensure_active_entity_visibility_ = function() {
|
||||
if (
|
||||
this.state_.active_room_entity !== undefined &&
|
||||
(
|
||||
this.state_.active_room_entity.get_room().editor_hidden === true ||
|
||||
this.state_.active_room_entity.get_room().editor_locked === true
|
||||
)
|
||||
) {
|
||||
delete this.state_.active_room_entity;
|
||||
delete this.state_.active_wall_entity;
|
||||
delete this.state_.active_point_entity;
|
||||
}
|
||||
|
||||
if (
|
||||
this.state_.active_surface_entity !== undefined &&
|
||||
(
|
||||
this.state_.active_surface_entity.get_surface().editor_hidden === true ||
|
||||
this.state_.active_surface_entity.get_surface().editor_locked === true
|
||||
)
|
||||
) {
|
||||
delete this.state_.active_surface_entity;
|
||||
delete this.state_.active_wall_entity;
|
||||
delete this.state_.active_point_entity;
|
||||
}
|
||||
|
||||
if (
|
||||
this.state_.active_tree_entity !== undefined &&
|
||||
(
|
||||
this.state_.active_tree_entity.get_tree().editor_hidden === true ||
|
||||
this.state_.active_tree_entity.get_tree().editor_locked === true
|
||||
)
|
||||
) {
|
||||
delete this.state_.active_tree_entity;
|
||||
}
|
||||
|
||||
if (
|
||||
this.state_.active_opening_entity !== undefined &&
|
||||
(
|
||||
this.state_.active_opening_entity.get_opening().editor_hidden === true ||
|
||||
this.state_.active_opening_entity.get_opening().editor_locked === true
|
||||
)
|
||||
) {
|
||||
delete this.state_.active_opening_entity;
|
||||
}
|
||||
|
||||
if (
|
||||
this.state_.active_light_source_entity !== undefined &&
|
||||
(
|
||||
this.state_.active_light_source_entity.get_light_source().editor_hidden === true ||
|
||||
this.state_.active_light_source_entity.get_light_source().editor_locked === true
|
||||
)
|
||||
) {
|
||||
delete this.state_.active_light_source_entity;
|
||||
}
|
||||
this.get_layer_types_().forEach(function(type) {
|
||||
const metadata = this.get_layer_type_meta_(type);
|
||||
const active_entity = this.state_[metadata.active_state_key];
|
||||
if (active_entity === undefined) {
|
||||
return;
|
||||
}
|
||||
const getter = active_entity[metadata.getter_name];
|
||||
if (typeof getter !== 'function') {
|
||||
return;
|
||||
}
|
||||
const active_object = getter.call(active_entity);
|
||||
if (
|
||||
active_object !== undefined &&
|
||||
(active_object.editor_hidden === true || active_object.editor_locked === true)
|
||||
) {
|
||||
delete this.state_[metadata.active_state_key];
|
||||
if (metadata.clears_geometry_selection === true) {
|
||||
delete this.state_.active_wall_entity;
|
||||
delete this.state_.active_point_entity;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1261,26 +1111,51 @@ beestat.component.card.floor_plan_editor.prototype.apply_pending_layer_selection
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the id key by object type.
|
||||
* Layer metadata by type.
|
||||
*
|
||||
* @param {string} type rooms|surfaces|trees
|
||||
* @param {string} type rooms|surfaces|openings|trees|light_sources
|
||||
*
|
||||
* @return {string}
|
||||
* @return {object|undefined}
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.get_layer_object_id_key_ = function(type) {
|
||||
if (type === 'rooms') {
|
||||
return 'room_id';
|
||||
beestat.component.card.floor_plan_editor.prototype.get_layer_type_meta_ = function(type) {
|
||||
return beestat.component.card.floor_plan_editor.layer_type_meta_[type];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all supported layer types.
|
||||
*
|
||||
* @return {string[]}
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.get_layer_types_ = function() {
|
||||
return Object.keys(beestat.component.card.floor_plan_editor.layer_type_meta_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deactivate active entity for a specific object id/type.
|
||||
*
|
||||
* @param {string} type rooms|surfaces|openings|trees|light_sources
|
||||
* @param {string} object_id
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.deactivate_active_entity_for_layer_object_ = function(type, object_id) {
|
||||
const metadata = this.get_layer_type_meta_(type);
|
||||
if (metadata === undefined) {
|
||||
return;
|
||||
}
|
||||
if (type === 'surfaces') {
|
||||
return 'surface_id';
|
||||
const active_entity = this.state_[metadata.active_state_key];
|
||||
if (active_entity === undefined) {
|
||||
return;
|
||||
}
|
||||
if (type === 'openings') {
|
||||
return 'opening_id';
|
||||
const getter = active_entity[metadata.getter_name];
|
||||
if (typeof getter !== 'function') {
|
||||
return;
|
||||
}
|
||||
if (type === 'light_sources') {
|
||||
return 'light_source_id';
|
||||
const active_object = getter.call(active_entity);
|
||||
if (
|
||||
active_object !== undefined &&
|
||||
active_object[metadata.id_key] === object_id
|
||||
) {
|
||||
active_entity.set_active(false);
|
||||
}
|
||||
return 'tree_id';
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1293,10 +1168,13 @@ beestat.component.card.floor_plan_editor.prototype.get_layer_object_id_key_ = fu
|
||||
* @return {object|undefined}
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.get_layer_object_by_id_ = function(group, type, object_id) {
|
||||
const metadata = this.get_layer_type_meta_(type);
|
||||
if (metadata === undefined) {
|
||||
return;
|
||||
}
|
||||
const collection = group[type] || [];
|
||||
const id_key = this.get_layer_object_id_key_(type);
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
if (collection[i][id_key] === object_id) {
|
||||
if (collection[i][metadata.id_key] === object_id) {
|
||||
return collection[i];
|
||||
}
|
||||
}
|
||||
@ -2570,17 +2448,6 @@ beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function
|
||||
beestat.floor_plan.queue_data_save_(floor_plan_id, 1000);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get cloned floor plan data.
|
||||
*
|
||||
* @param {number} floor_plan_id Floor plan ID
|
||||
*
|
||||
* @return {object} The modified floor plan data.
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.get_floor_plan_data_ = function(floor_plan_id) {
|
||||
return beestat.clone(beestat.cache.floor_plan[floor_plan_id].data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate the menu.
|
||||
*
|
||||
|
||||
@ -29,7 +29,6 @@ beestat.component.card.three_d = function() {
|
||||
};
|
||||
|
||||
// Things that update the scene that don't require a rerender.
|
||||
// TODO these probably need moved to the layer instead of here
|
||||
beestat.dispatcher.addEventListener(
|
||||
[
|
||||
'setting.visualize.data_type',
|
||||
@ -325,137 +324,74 @@ beestat.component.card.three_d.prototype.decorate_contents_ = function(parent) {
|
||||
);
|
||||
}
|
||||
|
||||
// Don't go before there's data.
|
||||
/* required_begin = moment.max(
|
||||
required_begin,
|
||||
moment.utc(thermostat.data_begin)
|
||||
);*/
|
||||
|
||||
// Don't go after now.
|
||||
/* required_end = moment.min(
|
||||
required_end,
|
||||
moment().subtract(1, 'hour')
|
||||
);*/
|
||||
|
||||
/**
|
||||
* If the needed data exists in the database and the runtime_sensor
|
||||
* cache is empty, then query the data. If the needed data does not exist in
|
||||
* the database, check every 2 seconds until it does.
|
||||
*/
|
||||
// TODO somewhat problematic because I need to check if data is synced from multiple thermostats now
|
||||
// if (beestat.thermostat.data_synced(this.thermostat_id_, required_begin, required_end) === true) {
|
||||
const sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map(this.floor_plan_id_));
|
||||
if (sensor_ids.length > 0) {
|
||||
if (true) {
|
||||
if (
|
||||
beestat.cache.data.three_d__runtime_sensor === undefined ||
|
||||
beestat.cache.data.three_d__runtime_thermostat === undefined
|
||||
) {
|
||||
// console.log('data is undefined need to load it');
|
||||
this.show_loading_('Fetching');
|
||||
if (
|
||||
beestat.cache.data.three_d__runtime_sensor === undefined ||
|
||||
beestat.cache.data.three_d__runtime_thermostat === undefined
|
||||
) {
|
||||
this.show_loading_('Fetching');
|
||||
|
||||
const value = [
|
||||
required_begin.format(),
|
||||
required_end.format()
|
||||
];
|
||||
const operator = 'between';
|
||||
const value = [
|
||||
required_begin.format(),
|
||||
required_end.format()
|
||||
];
|
||||
const operator = 'between';
|
||||
|
||||
const sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map(this.floor_plan_id_));
|
||||
const thermostat_ids = Object.keys(beestat.floor_plan.get_thermostat_ids_map(this.floor_plan_id_));
|
||||
// if (sensor_ids.length > 0) {
|
||||
const api_call = new beestat.api();
|
||||
const thermostat_ids = Object.keys(beestat.floor_plan.get_thermostat_ids_map(this.floor_plan_id_));
|
||||
const api_call = new beestat.api();
|
||||
|
||||
// Sensor data
|
||||
sensor_ids.forEach(function(sensor_id) {
|
||||
api_call.add_call(
|
||||
'runtime_sensor',
|
||||
'read',
|
||||
{
|
||||
'attributes': {
|
||||
'sensor_id': sensor_id,
|
||||
'timestamp': {
|
||||
'value': value,
|
||||
'operator': operator
|
||||
}
|
||||
}
|
||||
},
|
||||
'runtime_sensor_' + sensor_id
|
||||
);
|
||||
});
|
||||
|
||||
// Thermostat data
|
||||
thermostat_ids.forEach(function(thermostat_id) {
|
||||
api_call.add_call(
|
||||
'runtime_thermostat',
|
||||
'read',
|
||||
{
|
||||
'attributes': {
|
||||
'thermostat_id': thermostat_id,
|
||||
'timestamp': {
|
||||
'value': value,
|
||||
'operator': operator
|
||||
}
|
||||
}
|
||||
},
|
||||
'runtime_thermostat_' + thermostat_id
|
||||
);
|
||||
});
|
||||
|
||||
api_call.set_callback(function(response) {
|
||||
let runtime_sensors = [];
|
||||
let runtime_thermostats = [];
|
||||
for (let alias in response) {
|
||||
if (alias.includes('runtime_sensor_') === true) {
|
||||
runtime_sensors = runtime_sensors.concat(response[alias]);
|
||||
} else {
|
||||
runtime_thermostats = runtime_thermostats.concat(response[alias]);
|
||||
// Sensor data
|
||||
sensor_ids.forEach(function(sensor_id) {
|
||||
api_call.add_call(
|
||||
'runtime_sensor',
|
||||
'read',
|
||||
{
|
||||
'attributes': {
|
||||
'sensor_id': sensor_id,
|
||||
'timestamp': {
|
||||
'value': value,
|
||||
'operator': operator
|
||||
}
|
||||
}
|
||||
beestat.cache.set('data.three_d__runtime_sensor', runtime_sensors);
|
||||
beestat.cache.set('data.three_d__runtime_thermostat', runtime_thermostats);
|
||||
});
|
||||
},
|
||||
'runtime_sensor_' + sensor_id
|
||||
);
|
||||
});
|
||||
|
||||
api_call.send();
|
||||
|
||||
// }
|
||||
} else if (this.has_data_() === false) {
|
||||
console.info('has data false');
|
||||
/*chart_container.style('filter', 'blur(3px)');
|
||||
var no_data = $.createElement('div');
|
||||
no_data.style({
|
||||
'position': 'absolute',
|
||||
'top': 0,
|
||||
'left': 0,
|
||||
'width': '100%',
|
||||
'height': '100%',
|
||||
'display': 'flex',
|
||||
'flex-direction': 'column',
|
||||
'justify-content': 'center',
|
||||
'text-align': 'center'
|
||||
});
|
||||
no_data.innerText('No data to display');
|
||||
container.appendChild(no_data);*/
|
||||
}
|
||||
} else {
|
||||
this.show_loading_('Syncing');
|
||||
window.setTimeout(function() {
|
||||
new beestat.api()
|
||||
.add_call(
|
||||
'thermostat',
|
||||
'read_id',
|
||||
{
|
||||
'attributes': {
|
||||
'inactive': 0
|
||||
// Thermostat data
|
||||
thermostat_ids.forEach(function(thermostat_id) {
|
||||
api_call.add_call(
|
||||
'runtime_thermostat',
|
||||
'read',
|
||||
{
|
||||
'attributes': {
|
||||
'thermostat_id': thermostat_id,
|
||||
'timestamp': {
|
||||
'value': value,
|
||||
'operator': operator
|
||||
}
|
||||
},
|
||||
'thermostat'
|
||||
)
|
||||
.set_callback(function(response) {
|
||||
beestat.cache.set('thermostat', response);
|
||||
self.rerender();
|
||||
})
|
||||
.send();
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
'runtime_thermostat_' + thermostat_id
|
||||
);
|
||||
});
|
||||
|
||||
api_call.set_callback(function(response) {
|
||||
let runtime_sensors = [];
|
||||
let runtime_thermostats = [];
|
||||
for (let alias in response) {
|
||||
if (alias.includes('runtime_sensor_') === true) {
|
||||
runtime_sensors = runtime_sensors.concat(response[alias]);
|
||||
} else {
|
||||
runtime_thermostats = runtime_thermostats.concat(response[alias]);
|
||||
}
|
||||
}
|
||||
beestat.cache.set('data.three_d__runtime_sensor', runtime_sensors);
|
||||
beestat.cache.set('data.three_d__runtime_thermostat', runtime_thermostats);
|
||||
});
|
||||
|
||||
api_call.send();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -498,7 +434,6 @@ beestat.component.card.three_d.prototype.decorate_drawing_pane_ = function(paren
|
||||
});
|
||||
|
||||
// Set the initial date.
|
||||
// if (this.has_data_() === true) {
|
||||
this.update_scene_();
|
||||
this.scene_.render($(parent));
|
||||
|
||||
@ -895,15 +830,6 @@ beestat.component.card.three_d.prototype.apply_weather_setting_to_scene_ = funct
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get whether or not this user can access scene settings controls.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
beestat.component.card.three_d.prototype.can_access_scene_settings_ = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure local scene settings state exists.
|
||||
*/
|
||||
@ -1122,7 +1048,6 @@ beestat.component.card.three_d.prototype.decorate_scene_settings_panel_ = functi
|
||||
this.scene_settings_container_.innerHTML = '';
|
||||
this.scene_settings_panel_content_ = undefined;
|
||||
if (
|
||||
this.can_access_scene_settings_() !== true ||
|
||||
this.get_show_environment_() !== true ||
|
||||
this.scene_settings_menu_open_ !== true
|
||||
) {
|
||||
@ -1868,7 +1793,6 @@ beestat.component.card.three_d.prototype.update_fps_visibility_ = function() {
|
||||
}
|
||||
|
||||
const show = (
|
||||
this.can_access_scene_settings_() === true &&
|
||||
this.get_show_environment_() === true &&
|
||||
this.scene_settings_menu_open_ === true
|
||||
);
|
||||
@ -1954,7 +1878,7 @@ beestat.component.card.three_d.prototype.decorate_toolbar_ = function(parent) {
|
||||
);
|
||||
}
|
||||
|
||||
if (this.can_access_scene_settings_() === true && show_environment === true) {
|
||||
if (show_environment === true) {
|
||||
tile_group.add_tile(new beestat.component.tile()
|
||||
.set_icon('tune')
|
||||
.set_title('Scene Settings')
|
||||
@ -2560,6 +2484,31 @@ beestat.component.card.three_d.prototype.remove_global_listeners_ = function() {
|
||||
beestat.dispatcher.removeEventListener('resize.three_d');
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared teardown path for stale-instance disposal and normal disposal.
|
||||
*/
|
||||
beestat.component.card.three_d.prototype.teardown_ = function() {
|
||||
if (this.rerender_timeout_id_ !== undefined) {
|
||||
window.clearTimeout(this.rerender_timeout_id_);
|
||||
this.rerender_timeout_id_ = undefined;
|
||||
this.rerender_pending_delay_ms_ = undefined;
|
||||
}
|
||||
this.rerender_waiting_for_visibility_ = false;
|
||||
if (this.visibility_observer_ !== undefined) {
|
||||
this.visibility_observer_.disconnect();
|
||||
this.visibility_observer_ = undefined;
|
||||
}
|
||||
this.hide_loading_();
|
||||
window.clearInterval(this.fps_interval_);
|
||||
delete this.fps_interval_;
|
||||
this.remove_global_listeners_();
|
||||
|
||||
if (this.scene_ !== undefined) {
|
||||
this.scene_.dispose();
|
||||
delete this.scene_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Force teardown for stale card instances that were not formally disposed.
|
||||
*/
|
||||
@ -2569,49 +2518,12 @@ beestat.component.card.three_d.prototype.force_dispose_stale_instance_ = functio
|
||||
}
|
||||
|
||||
this.disposed_ = true;
|
||||
if (this.rerender_timeout_id_ !== undefined) {
|
||||
window.clearTimeout(this.rerender_timeout_id_);
|
||||
this.rerender_timeout_id_ = undefined;
|
||||
this.rerender_pending_delay_ms_ = undefined;
|
||||
}
|
||||
this.rerender_waiting_for_visibility_ = false;
|
||||
if (this.visibility_observer_ !== undefined) {
|
||||
this.visibility_observer_.disconnect();
|
||||
this.visibility_observer_ = undefined;
|
||||
}
|
||||
this.hide_loading_();
|
||||
window.clearInterval(this.fps_interval_);
|
||||
delete this.fps_interval_;
|
||||
this.remove_global_listeners_();
|
||||
|
||||
if (this.scene_ !== undefined) {
|
||||
this.scene_.dispose();
|
||||
delete this.scene_;
|
||||
}
|
||||
this.teardown_();
|
||||
};
|
||||
|
||||
beestat.component.card.three_d.prototype.dispose = function() {
|
||||
this.disposed_ = true;
|
||||
if (this.rerender_timeout_id_ !== undefined) {
|
||||
window.clearTimeout(this.rerender_timeout_id_);
|
||||
this.rerender_timeout_id_ = undefined;
|
||||
this.rerender_pending_delay_ms_ = undefined;
|
||||
}
|
||||
this.rerender_waiting_for_visibility_ = false;
|
||||
if (this.visibility_observer_ !== undefined) {
|
||||
this.visibility_observer_.disconnect();
|
||||
this.visibility_observer_ = undefined;
|
||||
}
|
||||
this.hide_loading_();
|
||||
|
||||
window.clearInterval(this.fps_interval_);
|
||||
delete this.fps_interval_;
|
||||
this.remove_global_listeners_();
|
||||
|
||||
if (this.scene_ !== undefined) {
|
||||
this.scene_.dispose();
|
||||
delete this.scene_;
|
||||
}
|
||||
this.teardown_();
|
||||
if (beestat.component.card.three_d.active_instance_ === this) {
|
||||
delete beestat.component.card.three_d.active_instance_;
|
||||
}
|
||||
|
||||
@ -256,3 +256,80 @@ beestat.component.floor_plan_entity.prototype.get_x = function() {
|
||||
beestat.component.floor_plan_entity.prototype.get_y = function() {
|
||||
return this.y_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect snap x/y coordinates from selected shape collections.
|
||||
*
|
||||
* @param {{
|
||||
* groups: object[],
|
||||
* shape_specs: Array<{collection: string, point_mode: string}>,
|
||||
* should_skip_shape: (function(object, object, object): boolean)=
|
||||
* }} options
|
||||
*
|
||||
* @return {{snap_x: number[], snap_y: number[]}}
|
||||
*/
|
||||
beestat.component.floor_plan_entity.prototype.collect_snap_points_ = function(options) {
|
||||
const snap_x = {};
|
||||
const snap_y = {};
|
||||
const groups = Array.isArray(options.groups) ? options.groups : [];
|
||||
const shape_specs = Array.isArray(options.shape_specs) ? options.shape_specs : [];
|
||||
const should_skip_shape = typeof options.should_skip_shape === 'function'
|
||||
? options.should_skip_shape
|
||||
: function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
groups.forEach(function(group) {
|
||||
if (group === undefined || group === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
shape_specs.forEach(function(shape_spec) {
|
||||
const shapes = group[shape_spec.collection];
|
||||
if (Array.isArray(shapes) !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
shapes.forEach(function(shape) {
|
||||
if (shape === undefined || shape.editor_hidden === true) {
|
||||
return;
|
||||
}
|
||||
if (should_skip_shape(shape, shape_spec, group) === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shape_spec.point_mode === 'point') {
|
||||
snap_x[Number(shape.x || 0)] = true;
|
||||
snap_y[Number(shape.y || 0)] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(shape.points) !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
shape.points.forEach(function(point) {
|
||||
const point_x = Number(point.x || 0);
|
||||
const point_y = Number(point.y || 0);
|
||||
if (shape_spec.point_mode === 'absolute') {
|
||||
snap_x[point_x] = true;
|
||||
snap_y[point_y] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
snap_x[point_x + Number(shape.x || 0)] = true;
|
||||
snap_y[point_y + Number(shape.y || 0)] = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
'snap_x': Object.keys(snap_x).map(function(key) {
|
||||
return Number(key);
|
||||
}),
|
||||
'snap_y': Object.keys(snap_y).map(function(key) {
|
||||
return Number(key);
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
@ -308,66 +308,42 @@ beestat.component.floor_plan_entity.light_source.prototype.after_mouseup_handler
|
||||
*/
|
||||
beestat.component.floor_plan_entity.light_source.prototype.update_snap_points_ = function() {
|
||||
const self = this;
|
||||
const snap_x = {};
|
||||
const snap_y = {};
|
||||
|
||||
const append_shapes = function(shapes, skip_self_light_source) {
|
||||
if (Array.isArray(shapes) !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
shapes.forEach(function(shape) {
|
||||
if (shape.editor_hidden === true) {
|
||||
return;
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
const groups = [this.group_];
|
||||
if (group_below !== undefined) {
|
||||
groups.push(group_below);
|
||||
}
|
||||
const snap_points = this.collect_snap_points_({
|
||||
'groups': groups,
|
||||
'shape_specs': [
|
||||
{
|
||||
'collection': 'rooms',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'surfaces',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'openings',
|
||||
'point_mode': 'absolute'
|
||||
},
|
||||
{
|
||||
'collection': 'light_sources',
|
||||
'point_mode': 'point'
|
||||
}
|
||||
|
||||
if (
|
||||
skip_self_light_source === true &&
|
||||
],
|
||||
'should_skip_shape': function(shape, shape_spec) {
|
||||
return (
|
||||
shape_spec.collection === 'light_sources' &&
|
||||
shape.light_source_id !== undefined &&
|
||||
self.light_source_ !== undefined &&
|
||||
self.light_source_.light_source_id === shape.light_source_id
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(shape.points) === true) {
|
||||
shape.points.forEach(function(point) {
|
||||
const is_opening = shape.opening_id !== undefined;
|
||||
const absolute_x = is_opening
|
||||
? Number(point.x || 0)
|
||||
: Number(point.x || 0) + Number(shape.x || 0);
|
||||
const absolute_y = is_opening
|
||||
? Number(point.y || 0)
|
||||
: Number(point.y || 0) + Number(shape.y || 0);
|
||||
snap_x[absolute_x] = true;
|
||||
snap_y[absolute_y] = true;
|
||||
});
|
||||
} else {
|
||||
snap_x[Number(shape.x || 0)] = true;
|
||||
snap_y[Number(shape.y || 0)] = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
append_shapes(this.group_.rooms, false);
|
||||
append_shapes(this.group_.surfaces, false);
|
||||
append_shapes(this.group_.openings, false);
|
||||
append_shapes(this.group_.light_sources, true);
|
||||
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
if (group_below !== undefined) {
|
||||
append_shapes(group_below.rooms, false);
|
||||
append_shapes(group_below.surfaces, false);
|
||||
append_shapes(group_below.openings, false);
|
||||
append_shapes(group_below.light_sources, false);
|
||||
}
|
||||
|
||||
this.snap_x_ = Object.keys(snap_x).map(function(key) {
|
||||
return Number(key);
|
||||
});
|
||||
this.snap_y_ = Object.keys(snap_y).map(function(key) {
|
||||
return Number(key);
|
||||
);
|
||||
}
|
||||
});
|
||||
this.snap_x_ = snap_points.snap_x;
|
||||
this.snap_y_ = snap_points.snap_y;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -441,58 +441,39 @@ beestat.component.floor_plan_entity.opening.prototype.clear_snap_lines_ = functi
|
||||
*/
|
||||
beestat.component.floor_plan_entity.opening.prototype.update_snap_points_ = function() {
|
||||
const self = this;
|
||||
const snap_x = {};
|
||||
const snap_y = {};
|
||||
|
||||
const append_shapes = function(shapes, skip_self_opening) {
|
||||
if (Array.isArray(shapes) !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
shapes.forEach(function(shape) {
|
||||
if (shape.editor_hidden === true || Array.isArray(shape.points) !== true) {
|
||||
return;
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
const groups = [this.group_];
|
||||
if (group_below !== undefined) {
|
||||
groups.push(group_below);
|
||||
}
|
||||
const snap_points = this.collect_snap_points_({
|
||||
'groups': groups,
|
||||
'shape_specs': [
|
||||
{
|
||||
'collection': 'rooms',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'surfaces',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'openings',
|
||||
'point_mode': 'absolute'
|
||||
}
|
||||
if (
|
||||
skip_self_opening === true &&
|
||||
],
|
||||
'should_skip_shape': function(shape, shape_spec) {
|
||||
return (
|
||||
shape_spec.collection === 'openings' &&
|
||||
self.opening_ !== undefined &&
|
||||
shape.opening_id !== undefined &&
|
||||
self.opening_.opening_id !== undefined &&
|
||||
shape.opening_id === self.opening_.opening_id
|
||||
) {
|
||||
return;
|
||||
}
|
||||
shape.points.forEach(function(point) {
|
||||
const is_opening = shape.opening_id !== undefined;
|
||||
const absolute_x = is_opening
|
||||
? Number(point.x || 0)
|
||||
: Number(point.x || 0) + Number(shape.x || 0);
|
||||
const absolute_y = is_opening
|
||||
? Number(point.y || 0)
|
||||
: Number(point.y || 0) + Number(shape.y || 0);
|
||||
snap_x[absolute_x] = true;
|
||||
snap_y[absolute_y] = true;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
append_shapes(this.group_.rooms, false);
|
||||
append_shapes(this.group_.surfaces, false);
|
||||
append_shapes(this.group_.openings, true);
|
||||
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
if (group_below !== undefined) {
|
||||
append_shapes(group_below.rooms, false);
|
||||
append_shapes(group_below.surfaces, false);
|
||||
append_shapes(group_below.openings, false);
|
||||
}
|
||||
|
||||
this.snap_x_ = Object.keys(snap_x).map(function(key) {
|
||||
return Number(key);
|
||||
});
|
||||
this.snap_y_ = Object.keys(snap_y).map(function(key) {
|
||||
return Number(key);
|
||||
);
|
||||
}
|
||||
});
|
||||
this.snap_x_ = snap_points.snap_x;
|
||||
this.snap_y_ = snap_points.snap_y;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -195,9 +195,6 @@ beestat.component.floor_plan_entity.prototype.decorate_walls_ = function(parent)
|
||||
wall_entity.addEventListener('mousedown', function() {
|
||||
wall_entity.set_active(true);
|
||||
});
|
||||
wall_entity.addEventListener('mousedown', function() {
|
||||
wall_entity.set_active(true);
|
||||
});
|
||||
|
||||
// Add toolbar button on activate.
|
||||
wall_entity.addEventListener('activate', function() {
|
||||
@ -305,60 +302,26 @@ beestat.component.floor_plan_entity.room.prototype.set_active = function(active)
|
||||
* Pre-generate a list of snappable x/y values.
|
||||
*/
|
||||
beestat.component.floor_plan_entity.room.prototype.update_snap_points_ = function() {
|
||||
const snap_x = {};
|
||||
const snap_y = {};
|
||||
|
||||
// Snap to rooms in this group.
|
||||
this.group_.rooms.forEach(function(room) {
|
||||
if (room.editor_hidden === true) {
|
||||
return;
|
||||
}
|
||||
room.points.forEach(function(point) {
|
||||
snap_x[point.x + room.x] = true;
|
||||
snap_y[point.y + room.y] = true;
|
||||
});
|
||||
});
|
||||
(this.group_.openings || []).forEach(function(opening) {
|
||||
if (opening.editor_hidden === true || Array.isArray(opening.points) !== true) {
|
||||
return;
|
||||
}
|
||||
opening.points.forEach(function(point) {
|
||||
// Opening points are stored in absolute editor coordinates.
|
||||
snap_x[point.x] = true;
|
||||
snap_y[point.y] = true;
|
||||
});
|
||||
});
|
||||
|
||||
// Snap to rooms in the group under this one.
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
const groups = [this.group_];
|
||||
if (group_below !== undefined) {
|
||||
group_below.rooms.forEach(function(room) {
|
||||
if (room.editor_hidden === true) {
|
||||
return;
|
||||
}
|
||||
room.points.forEach(function(point) {
|
||||
snap_x[point.x + room.x] = true;
|
||||
snap_y[point.y + room.y] = true;
|
||||
});
|
||||
});
|
||||
(group_below.openings || []).forEach(function(opening) {
|
||||
if (opening.editor_hidden === true || Array.isArray(opening.points) !== true) {
|
||||
return;
|
||||
}
|
||||
opening.points.forEach(function(point) {
|
||||
// Opening points are stored in absolute editor coordinates.
|
||||
snap_x[point.x] = true;
|
||||
snap_y[point.y] = true;
|
||||
});
|
||||
});
|
||||
groups.push(group_below);
|
||||
}
|
||||
|
||||
this.snap_x_ = Object.keys(snap_x).map(function(key) {
|
||||
return Number(key);
|
||||
});
|
||||
this.snap_y_ = Object.keys(snap_y).map(function(key) {
|
||||
return Number(key);
|
||||
const snap_points = this.collect_snap_points_({
|
||||
'groups': groups,
|
||||
'shape_specs': [
|
||||
{
|
||||
'collection': 'rooms',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'openings',
|
||||
'point_mode': 'absolute'
|
||||
}
|
||||
]
|
||||
});
|
||||
this.snap_x_ = snap_points.snap_x;
|
||||
this.snap_y_ = snap_points.snap_y;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -165,43 +165,28 @@ beestat.component.floor_plan_entity.surface.prototype.set_active = function(acti
|
||||
* Pre-generate a list of snappable x/y values.
|
||||
*/
|
||||
beestat.component.floor_plan_entity.surface.prototype.update_snap_points_ = function() {
|
||||
const snap_x = {};
|
||||
const snap_y = {};
|
||||
|
||||
const append_shapes = function(shapes) {
|
||||
if (shapes === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
shapes.forEach(function(shape) {
|
||||
if (shape.editor_hidden === true || Array.isArray(shape.points) !== true) {
|
||||
return;
|
||||
}
|
||||
shape.points.forEach(function(point) {
|
||||
const is_opening = shape.opening_id !== undefined;
|
||||
const absolute_x = is_opening ? Number(point.x || 0) : Number(point.x || 0) + Number(shape.x || 0);
|
||||
const absolute_y = is_opening ? Number(point.y || 0) : Number(point.y || 0) + Number(shape.y || 0);
|
||||
snap_x[absolute_x] = true;
|
||||
snap_y[absolute_y] = true;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
append_shapes(this.group_.rooms);
|
||||
append_shapes(this.group_.surfaces);
|
||||
append_shapes(this.group_.openings);
|
||||
|
||||
const group_below = this.floor_plan_.get_group_below(this.group_);
|
||||
const groups = [this.group_];
|
||||
if (group_below !== undefined) {
|
||||
append_shapes(group_below.rooms);
|
||||
append_shapes(group_below.surfaces);
|
||||
append_shapes(group_below.openings);
|
||||
groups.push(group_below);
|
||||
}
|
||||
|
||||
this.snap_x_ = Object.keys(snap_x).map(function(key) {
|
||||
return Number(key);
|
||||
});
|
||||
this.snap_y_ = Object.keys(snap_y).map(function(key) {
|
||||
return Number(key);
|
||||
const snap_points = this.collect_snap_points_({
|
||||
'groups': groups,
|
||||
'shape_specs': [
|
||||
{
|
||||
'collection': 'rooms',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'surfaces',
|
||||
'point_mode': 'relative'
|
||||
},
|
||||
{
|
||||
'collection': 'openings',
|
||||
'point_mode': 'absolute'
|
||||
}
|
||||
]
|
||||
});
|
||||
this.snap_x_ = snap_points.snap_x;
|
||||
this.snap_y_ = snap_points.snap_y;
|
||||
};
|
||||
|
||||
@ -112,34 +112,6 @@ beestat.component.scene.room_floor_thickness = 6;
|
||||
*/
|
||||
beestat.component.scene.surface_z_lift = 0.75;
|
||||
|
||||
/**
|
||||
* Default number of decorative trees to place around the environment.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
beestat.component.scene.environment_tree_count = 14;
|
||||
|
||||
/**
|
||||
* Toggle tree foliage visibility for environment trees.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
beestat.component.scene.environment_tree_foliage_enabled = true;
|
||||
|
||||
/**
|
||||
* Debug opacity for round/oval canopies when foliage is visible.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
beestat.component.scene.debug_tree_canopy_opacity = 1;
|
||||
|
||||
/**
|
||||
* Keep round/oval branch meshes visible even when foliage is visible.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
beestat.component.scene.debug_show_branches_with_foliage = true;
|
||||
|
||||
/**
|
||||
* Round/oval primary branch density in branches per height unit.
|
||||
*
|
||||
@ -221,27 +193,6 @@ beestat.component.scene.sun_light_intensity = 0.6;
|
||||
*/
|
||||
beestat.component.scene.moon_light_intensity = 0.13125;
|
||||
|
||||
/**
|
||||
* Peak per-room interior light intensity used at night.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
beestat.component.scene.interior_light_intensity = 0.9;
|
||||
|
||||
/**
|
||||
* Max number of interior point lights allowed to cast shadows.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
beestat.component.scene.interior_light_shadow_max = 1;
|
||||
|
||||
/**
|
||||
* Number of star sprites generated in the sky dome.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
beestat.component.scene.star_count = 900;
|
||||
|
||||
/**
|
||||
* Minimum star sprite size.
|
||||
*
|
||||
@ -428,7 +379,6 @@ beestat.component.scene.prototype.rerender = function() {
|
||||
this.add_main_group_();
|
||||
this.add_floor_plan_();
|
||||
}.bind(this));
|
||||
this.apply_appearance_rotation_to_lights_();
|
||||
|
||||
// Ensure everything gets updated with the latest info.
|
||||
if (this.rendered_ === true) {
|
||||
@ -550,8 +500,6 @@ beestat.component.scene.prototype.reset_celestial_lights_for_rerender_ = functio
|
||||
delete this.celestial_light_group_;
|
||||
delete this.sun_light_;
|
||||
delete this.moon_light_;
|
||||
delete this.sun_light_helper_;
|
||||
delete this.moon_light_helper_;
|
||||
delete this.sun_path_line_;
|
||||
delete this.sun_visual_group_;
|
||||
delete this.sun_core_mesh_;
|
||||
@ -591,19 +539,6 @@ beestat.component.scene.prototype.get_scene_setting_ = function(key) {
|
||||
return beestat.component.scene.default_settings[key];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all currently effective scene settings.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
beestat.component.scene.prototype.get_scene_settings = function() {
|
||||
const current_settings = Object.assign({}, beestat.component.scene.default_settings);
|
||||
if (this.scene_settings_ !== undefined) {
|
||||
Object.assign(current_settings, this.scene_settings_);
|
||||
}
|
||||
return current_settings;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update scene settings.
|
||||
*
|
||||
@ -695,25 +630,12 @@ beestat.component.scene.prototype.decorate_ = function(parent) {
|
||||
this.scene_settings_ = {};
|
||||
}
|
||||
|
||||
this.debug_ = {
|
||||
'axes': false,
|
||||
'directional_light_helpers': false,
|
||||
'sun_light_helper': false,
|
||||
'moon_light_helper': false,
|
||||
'watcher': false,
|
||||
'roof_edges': false,
|
||||
'straight_skeleton': false,
|
||||
'openings': false,
|
||||
'opening_cutters': false,
|
||||
'hide_tree_branches': false,
|
||||
'light_source_orbs': false
|
||||
};
|
||||
this.room_interaction_enabled_ = true;
|
||||
|
||||
this.width_ = this.initial_width_ || this.state_.scene_width || 800;
|
||||
this.height_ = 500;
|
||||
|
||||
this.add_scene_(parent);
|
||||
this.add_scene_();
|
||||
this.add_renderer_(parent);
|
||||
this.add_camera_();
|
||||
this.add_controls_(parent);
|
||||
@ -783,37 +705,9 @@ beestat.component.scene.prototype.set_initial_camera_state = function(camera_sta
|
||||
|
||||
/**
|
||||
* Add the scene. Everything gets added to the scene.
|
||||
*
|
||||
* @param {rocket.Elements} parent Parent
|
||||
*/
|
||||
beestat.component.scene.prototype.add_scene_ = function(parent) {
|
||||
beestat.component.scene.prototype.add_scene_ = function() {
|
||||
this.scene_ = new THREE.Scene();
|
||||
|
||||
if (this.debug_.axes === true) {
|
||||
this.scene_.add(
|
||||
new THREE.AxesHelper(800)
|
||||
.setColors(
|
||||
0xff0000,
|
||||
0x00ff00,
|
||||
0x0000ff
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.debug_.watcher === true) {
|
||||
this.debug_info_ = {};
|
||||
this.debug_container_ = $.createElement('div').style({
|
||||
'position': 'absolute',
|
||||
'top': (beestat.style.size.gutter / 2),
|
||||
'left': (beestat.style.size.gutter / 2),
|
||||
'padding': (beestat.style.size.gutter / 2),
|
||||
'background': 'rgba(0, 0, 0, 0.5)',
|
||||
'color': '#fff',
|
||||
'font-family': 'Consolas, Courier, Monospace',
|
||||
'white-space': 'pre'
|
||||
});
|
||||
parent.appendChild(this.debug_container_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1034,185 +928,6 @@ beestat.component.scene.prototype.update_ = function() {
|
||||
}
|
||||
|
||||
this.update_tree_foliage_season_();
|
||||
|
||||
// Update debug watcher
|
||||
if (this.debug_.watcher === true) {
|
||||
this.debug_info_.sun_light_intensity = this.sun_light_ !== undefined ? this.sun_light_.intensity.toFixed(3) : 'N/A';
|
||||
this.debug_info_.moon_light_intensity = this.moon_light_ !== undefined ? this.moon_light_.intensity.toFixed(3) : 'N/A';
|
||||
this.update_debug_();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a helpful debug window that can be refreshed with the contents of
|
||||
* this.debug_info_.
|
||||
*
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.scene.prototype.add_debug_ = function(parent) {
|
||||
if (this.debug_.watcher === true) {
|
||||
this.debug_info_ = {};
|
||||
this.debug_container_ = $.createElement('div').style({
|
||||
'position': 'absolute',
|
||||
'top': (beestat.style.size.gutter / 2),
|
||||
'left': (beestat.style.size.gutter / 2),
|
||||
'padding': (beestat.style.size.gutter / 2),
|
||||
'background': 'rgba(0, 0, 0, 0.5)',
|
||||
'color': '#fff',
|
||||
'font-family': 'Consolas, Courier, Monospace',
|
||||
'white-space': 'pre'
|
||||
});
|
||||
parent.appendChild(this.debug_container_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the debug window.
|
||||
*/
|
||||
beestat.component.scene.prototype.update_debug_ = function() {
|
||||
if (this.debug_.watcher === true) {
|
||||
this.debug_container_.innerHTML(
|
||||
JSON.stringify(this.debug_info_, null, 2)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add red outline visualization for exposed ceiling areas (future roof locations).
|
||||
*/
|
||||
beestat.component.scene.prototype.add_roof_outline_debug_ = function() {
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
|
||||
const exposed_areas = this.compute_exposed_ceiling_areas_(floor_plan);
|
||||
|
||||
// Create layer for roof outlines
|
||||
const roof_outlines_layer = new THREE.Group();
|
||||
this.floor_plan_group_.add(roof_outlines_layer);
|
||||
this.layers_['roof_outlines'] = roof_outlines_layer;
|
||||
|
||||
// Render each exposed area as red outline
|
||||
exposed_areas.forEach(function(area) {
|
||||
area.polygons.forEach(function(polygon) {
|
||||
if (polygon.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create line points
|
||||
const points = [];
|
||||
polygon.forEach(function(point) {
|
||||
points.push(new THREE.Vector3(point.x, point.y, area.ceiling_z));
|
||||
});
|
||||
// Close the loop
|
||||
points.push(new THREE.Vector3(polygon[0].x, polygon[0].y, area.ceiling_z));
|
||||
|
||||
// Create red line
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints(points);
|
||||
const material = new THREE.LineBasicMaterial({
|
||||
'color': 0xff0000, // Red
|
||||
'linewidth': 2
|
||||
});
|
||||
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.layers.set(beestat.component.scene.layer_visible);
|
||||
roof_outlines_layer.add(line);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Visualize the straight skeleton for each roof polygon with debug lines.
|
||||
*/
|
||||
beestat.component.scene.prototype.add_roof_skeleton_debug_ = function() {
|
||||
const skeleton_builder = this.get_skeleton_builder_();
|
||||
if (skeleton_builder === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
const exposed_areas = this.compute_exposed_ceiling_areas_(floor_plan);
|
||||
|
||||
// Create layer for skeleton debug lines
|
||||
const skeleton_debug_layer = new THREE.Group();
|
||||
this.floor_plan_group_.add(skeleton_debug_layer);
|
||||
this.layers_['roof_skeleton_debug'] = skeleton_debug_layer;
|
||||
|
||||
let total_polygons = 0;
|
||||
let successful_skeletons = 0;
|
||||
|
||||
// Process each exposed area
|
||||
exposed_areas.forEach(function(area) {
|
||||
area.polygons.forEach(function(polygon) {
|
||||
if (polygon.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
total_polygons++;
|
||||
|
||||
try {
|
||||
// Simplify polygon to remove self-intersections and clean up topology
|
||||
// This splits complex polygons (L-shapes, T-shapes) into simpler ones
|
||||
const simplified = ClipperLib.Clipper.SimplifyPolygon(
|
||||
polygon,
|
||||
ClipperLib.PolyFillType.pftNonZero
|
||||
);
|
||||
|
||||
// SimplifyPolygon can return multiple polygons if the original was self-intersecting
|
||||
simplified.forEach(function(simple_polygon) {
|
||||
if (simple_polygon.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert ClipperLib format {x, y} to SkeletonBuilder format [[x, y], ...]
|
||||
const ring = simple_polygon.map(function(point) {
|
||||
return [point.x, point.y];
|
||||
});
|
||||
// Close the ring by repeating the first point
|
||||
ring.push([simple_polygon[0].x, simple_polygon[0].y]);
|
||||
|
||||
// Build the straight skeleton
|
||||
const coordinates = [ring]; // Array of rings (outer ring only, no holes)
|
||||
const result = skeleton_builder.buildFromPolygon(coordinates);
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
successful_skeletons++;
|
||||
|
||||
// Visualize each skeleton polygon face with blue lines
|
||||
result.polygons.forEach(function(face) {
|
||||
if (face.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create line points from the face vertices
|
||||
const points = [];
|
||||
face.forEach(function(vertex_index) {
|
||||
const vertex = result.vertices[vertex_index];
|
||||
points.push(new THREE.Vector3(vertex[0], vertex[1], area.ceiling_z));
|
||||
});
|
||||
// Close the loop
|
||||
const first_vertex = result.vertices[face[0]];
|
||||
points.push(new THREE.Vector3(first_vertex[0], first_vertex[1], area.ceiling_z));
|
||||
|
||||
// Create blue line for skeleton edges
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints(points);
|
||||
const material = new THREE.LineBasicMaterial({
|
||||
'color': 0x00ffff, // Cyan
|
||||
'linewidth': 1
|
||||
});
|
||||
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.layers.set(beestat.component.scene.layer_visible);
|
||||
skeleton_debug_layer.add(line);
|
||||
});
|
||||
}); // End simplified.forEach
|
||||
} catch (error) {
|
||||
console.error('Error building skeleton for polygon:', error, polygon);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -66,9 +66,6 @@ beestat.component.scene.prototype.update_tree_foliage_season_ = function() {
|
||||
}
|
||||
mesh.material.color.copy(state.color);
|
||||
mesh.userData.base_tree_foliage_color = state.color.getHex();
|
||||
mesh.material.opacity = beestat.component.scene.debug_tree_canopy_opacity;
|
||||
mesh.material.transparent = beestat.component.scene.debug_tree_canopy_opacity < 1;
|
||||
mesh.material.depthWrite = beestat.component.scene.debug_tree_canopy_opacity >= 1;
|
||||
mesh.material.needsUpdate = true;
|
||||
mesh.visible = tree_foliage_enabled === true;
|
||||
}
|
||||
@ -78,11 +75,7 @@ beestat.component.scene.prototype.update_tree_foliage_season_ = function() {
|
||||
for (let i = 0; i < this.tree_branch_groups_.length; i++) {
|
||||
const branch_group = this.tree_branch_groups_[i];
|
||||
if (branch_group !== undefined) {
|
||||
// Hide branches when canopy is visible; show them when canopy is not visible.
|
||||
// Debug override can force branch meshes hidden at all times.
|
||||
branch_group.visible =
|
||||
this.debug_.hide_tree_branches !== true &&
|
||||
tree_branch_enabled === true;
|
||||
branch_group.visible = tree_branch_enabled === true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,18 +91,7 @@ beestat.component.scene.prototype.add_floor_plan_ = function() {
|
||||
self.add_walls_(walls_layer, group);
|
||||
});
|
||||
|
||||
let opening_cutter_debug_layer;
|
||||
if (this.debug_.opening_cutters === true) {
|
||||
opening_cutter_debug_layer = new THREE.Group();
|
||||
this.floor_plan_group_.add(opening_cutter_debug_layer);
|
||||
this.layers_['opening_cutters_debug'] = opening_cutter_debug_layer;
|
||||
}
|
||||
|
||||
this.apply_opening_cuts_(
|
||||
walls_layer,
|
||||
floor_plan,
|
||||
opening_cutter_debug_layer
|
||||
);
|
||||
this.apply_opening_cuts_(walls_layer, floor_plan);
|
||||
|
||||
const openings_layer = new THREE.Group();
|
||||
this.floor_plan_group_.add(openings_layer);
|
||||
@ -119,27 +108,9 @@ beestat.component.scene.prototype.add_floor_plan_ = function() {
|
||||
self.add_light_sources_(light_sources_layer, group);
|
||||
});
|
||||
|
||||
if (this.debug_.openings === true) {
|
||||
const openings_debug_layer = new THREE.Group();
|
||||
this.floor_plan_group_.add(openings_debug_layer);
|
||||
this.layers_['openings_debug'] = openings_debug_layer;
|
||||
|
||||
floor_plan.data.groups.forEach(function(group) {
|
||||
self.add_openings_debug_(openings_debug_layer, group);
|
||||
});
|
||||
}
|
||||
|
||||
// Add roofs using straight skeleton
|
||||
this.add_roofs_();
|
||||
|
||||
if (this.debug_.roof_edges) {
|
||||
this.add_roof_outline_debug_();
|
||||
}
|
||||
|
||||
if (this.debug_.straight_skeleton) {
|
||||
this.add_roof_skeleton_debug_();
|
||||
}
|
||||
|
||||
this.add_environment_();
|
||||
};
|
||||
|
||||
|
||||
@ -40,15 +40,6 @@ beestat.component.scene.prototype.add_directional_lights_ = function() {
|
||||
this.static_light_group_.add(top_light);
|
||||
this.directional_lights_.push(top_light);
|
||||
|
||||
// Add helpers for debugging
|
||||
if (this.debug_.directional_light_helpers === true) {
|
||||
this.directional_light_helpers_ = [];
|
||||
this.directional_lights_.forEach((light) => {
|
||||
const helper = new THREE.DirectionalLightHelper(light, 100);
|
||||
this.static_light_group_.add(helper);
|
||||
this.directional_light_helpers_.push(helper);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -80,7 +71,6 @@ beestat.component.scene.prototype.add_static_lights_ = function() {
|
||||
|
||||
// Add directional fill lights
|
||||
this.add_directional_lights_();
|
||||
this.apply_appearance_rotation_to_lights_();
|
||||
};
|
||||
|
||||
|
||||
@ -209,14 +199,6 @@ beestat.component.scene.prototype.add_celestial_lights_ = function() {
|
||||
this.sun_glow_sprite_.renderOrder = 11;
|
||||
this.sun_visual_group_.add(this.sun_glow_sprite_);
|
||||
|
||||
if (this.debug_.sun_light_helper === true) {
|
||||
this.sun_light_helper_ = new THREE.DirectionalLightHelper(
|
||||
this.sun_light_,
|
||||
100
|
||||
);
|
||||
this.celestial_light_group_.add(this.sun_light_helper_);
|
||||
}
|
||||
|
||||
// Moon light
|
||||
this.moon_light_ = new THREE.DirectionalLight(
|
||||
0xaaccff, // Cool bluish color for moonlight
|
||||
@ -258,17 +240,7 @@ beestat.component.scene.prototype.add_celestial_lights_ = function() {
|
||||
this.moon_sprite_.scale.set(405, 405, 1);
|
||||
this.moon_visual_group_.add(this.moon_sprite_);
|
||||
|
||||
if (this.debug_.moon_light_helper === true) {
|
||||
this.moon_light_helper_ = new THREE.DirectionalLightHelper(
|
||||
this.moon_light_,
|
||||
100
|
||||
);
|
||||
this.celestial_light_group_.add(this.moon_light_helper_);
|
||||
}
|
||||
|
||||
this.add_stars_();
|
||||
|
||||
this.apply_appearance_rotation_to_lights_();
|
||||
};
|
||||
|
||||
|
||||
@ -397,17 +369,6 @@ beestat.component.scene.prototype.update_sun_path_arc_ = function(date, latitude
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Static (ambient/directional fill) lights should not rotate with floor-plan
|
||||
* appearance. Celestial lights are handled in update_celestial_lights_.
|
||||
*/
|
||||
beestat.component.scene.prototype.apply_appearance_rotation_to_lights_ = function() {
|
||||
if (this.static_light_group_ !== undefined) {
|
||||
this.static_light_group_.rotation.y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Build target sun colors from altitude.
|
||||
* Warmer near horizon and more neutral when the sun is high.
|
||||
@ -506,12 +467,6 @@ beestat.component.scene.prototype.update_celestial_lights_ = function(date, lati
|
||||
Math.min(1, (-sun_pos.altitude - 0.05) / 0.25)
|
||||
);
|
||||
|
||||
const interior_night_factor = Math.max(
|
||||
0,
|
||||
Math.min(1, (-sun_pos.altitude + 0.03) / 0.3)
|
||||
);
|
||||
this.target_interior_light_intensity_ =
|
||||
beestat.component.scene.interior_light_intensity * interior_night_factor;
|
||||
const max_sun_intensity = Math.max(0.0001, Number(beestat.component.scene.sun_light_intensity || 0.0001));
|
||||
const normalized_sun_brightness = Math.max(
|
||||
0,
|
||||
@ -576,18 +531,6 @@ beestat.component.scene.prototype.update_celestial_lights_ = function(date, lati
|
||||
: moon_intensity;
|
||||
}
|
||||
this.target_moon_intensity_ *= cloud_dimming;
|
||||
|
||||
// Update helpers
|
||||
if (this.debug_.sun_light_helper) {
|
||||
this.sun_light_.updateMatrixWorld();
|
||||
this.sun_light_.target.updateMatrixWorld();
|
||||
this.sun_light_helper_.update();
|
||||
}
|
||||
if (this.debug_.moon_light_helper) {
|
||||
this.moon_light_.updateMatrixWorld();
|
||||
this.moon_light_.target.updateMatrixWorld();
|
||||
this.moon_light_helper_.update();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -607,14 +550,6 @@ beestat.component.scene.prototype.update_celestial_light_intensities_ = function
|
||||
if (this.target_moon_intensity_ === undefined) {
|
||||
this.target_moon_intensity_ = 0;
|
||||
}
|
||||
if (this.target_interior_light_intensity_ === undefined) {
|
||||
const hour = this.date_ !== undefined ? Number(this.date_.format('H')) : 12;
|
||||
this.target_interior_light_intensity_ = (
|
||||
(hour >= 19 || hour <= 5)
|
||||
? beestat.component.scene.interior_light_intensity
|
||||
: 0
|
||||
);
|
||||
}
|
||||
if (this.target_light_source_intensity_multiplier_ === undefined) {
|
||||
const hour = this.date_ !== undefined ? Number(this.date_.format('H')) : 12;
|
||||
this.target_light_source_intensity_multiplier_ = (hour >= 19 || hour <= 5) ? 1 : 0;
|
||||
@ -640,11 +575,6 @@ beestat.component.scene.prototype.update_celestial_light_intensities_ = function
|
||||
const color_lerp_factor = 0.08;
|
||||
this.sun_light_.color.lerp(this.target_sun_light_color_, color_lerp_factor);
|
||||
|
||||
if (this.interior_lights_ !== undefined) {
|
||||
this.interior_lights_.forEach((light) => {
|
||||
light.intensity += (this.target_interior_light_intensity_ - light.intensity) * lerp_factor;
|
||||
});
|
||||
}
|
||||
if (Array.isArray(this.light_sources_) === true) {
|
||||
this.light_sources_.forEach((light) => {
|
||||
const base_intensity = Number(light.userData.base_intensity || 0);
|
||||
@ -789,29 +719,6 @@ beestat.component.scene.prototype.add_light_sources_ = function(layer, group) {
|
||||
this.light_sources_ = [];
|
||||
}
|
||||
|
||||
if (this.debug_.light_source_orbs === true) {
|
||||
if (this.light_source_marker_geometry_ === undefined) {
|
||||
this.light_source_marker_geometry_ = new THREE.SphereGeometry(2.2, 12, 12);
|
||||
}
|
||||
if (this.light_source_glow_geometry_ === undefined) {
|
||||
this.light_source_glow_geometry_ = new THREE.SphereGeometry(6, 16, 16);
|
||||
}
|
||||
if (this.light_source_marker_material_ === undefined) {
|
||||
this.light_source_marker_material_ = new THREE.MeshStandardMaterial({
|
||||
'roughness': 0.2,
|
||||
'metalness': 0.05
|
||||
});
|
||||
}
|
||||
if (this.light_source_glow_material_ === undefined) {
|
||||
this.light_source_glow_material_ = new THREE.MeshBasicMaterial({
|
||||
'transparent': true,
|
||||
'opacity': 0.28,
|
||||
'depthWrite': false,
|
||||
'blending': THREE.AdditiveBlending
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const group_elevation = Number(group.elevation || 0);
|
||||
const floor_thickness = Number(beestat.component.scene.room_floor_thickness || 0);
|
||||
const user_light_cast_shadows = this.get_scene_setting_('light_user_cast_shadows') === true;
|
||||
@ -830,33 +737,6 @@ beestat.component.scene.prototype.add_light_sources_ = function(layer, group) {
|
||||
const light_intensity = 0.9 * intensity_level;
|
||||
const light_color = this.get_light_color_from_temperature_(light_source.temperature_k);
|
||||
|
||||
if (this.debug_.light_source_orbs === true) {
|
||||
const marker = new THREE.Mesh(
|
||||
this.light_source_marker_geometry_,
|
||||
this.light_source_marker_material_.clone()
|
||||
);
|
||||
marker.material.color.copy(light_color);
|
||||
marker.material.emissive.copy(light_color);
|
||||
marker.material.emissiveIntensity = 0.9 + (intensity_level * 0.35);
|
||||
marker.position.set(x, y, z);
|
||||
marker.castShadow = false;
|
||||
marker.receiveShadow = false;
|
||||
marker.userData.is_light_source = true;
|
||||
layer.add(marker);
|
||||
|
||||
const glow = new THREE.Mesh(
|
||||
this.light_source_glow_geometry_,
|
||||
this.light_source_glow_material_.clone()
|
||||
);
|
||||
glow.material.color.copy(light_color);
|
||||
glow.material.opacity = 0.15 + (intensity_level * 0.08);
|
||||
glow.position.set(x, y, z);
|
||||
glow.castShadow = false;
|
||||
glow.receiveShadow = false;
|
||||
glow.userData.is_light_source = true;
|
||||
layer.add(glow);
|
||||
}
|
||||
|
||||
const light = new THREE.PointLight(light_color, light_intensity, 240, 2);
|
||||
light.userData.base_intensity = light_intensity;
|
||||
light.intensity = light_intensity * Number(this.target_light_source_intensity_multiplier_ || 0);
|
||||
@ -910,61 +790,4 @@ beestat.component.scene.prototype.update_user_light_shadow_settings_ = function(
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add warm interior point lights, one per room. Lights are invisible and their
|
||||
* intensity is animated based on night/day state.
|
||||
*
|
||||
* @param {object} floor_plan The floor plan data.
|
||||
*/
|
||||
beestat.component.scene.prototype.add_interior_lights_ = function(floor_plan) {
|
||||
this.interior_lights_ = [];
|
||||
this.interior_light_group_ = new THREE.Group();
|
||||
this.floor_plan_group_.add(this.interior_light_group_);
|
||||
this.layers_['interior_lights'] = this.interior_light_group_;
|
||||
let shadowed_light_count = 0;
|
||||
|
||||
floor_plan.data.groups.forEach(function(group) {
|
||||
group.rooms.forEach((room) => {
|
||||
if (room.points === undefined || room.points.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
const geojson_polygon = [];
|
||||
room.points.forEach(function(point) {
|
||||
geojson_polygon.push([
|
||||
point.x,
|
||||
point.y
|
||||
]);
|
||||
});
|
||||
const light_point = polylabel([geojson_polygon]);
|
||||
|
||||
const group_elevation = Number(group.elevation || 0);
|
||||
const room_height = Number(room.height || group.height || 96);
|
||||
const room_elevation = Number(room.elevation !== undefined ? room.elevation : group_elevation);
|
||||
|
||||
const light = new THREE.PointLight(0xffd79a, 0, 170, 2);
|
||||
light.position.set(
|
||||
Number(room.x || 0) + light_point[0],
|
||||
Number(room.y || 0) + light_point[1],
|
||||
-room_elevation - (room_height * 0.45)
|
||||
);
|
||||
if (shadowed_light_count < beestat.component.scene.interior_light_shadow_max) {
|
||||
light.castShadow = true;
|
||||
light.shadow.mapSize.width = 512;
|
||||
light.shadow.mapSize.height = 512;
|
||||
light.shadow.bias = -0.0012;
|
||||
light.shadow.normalBias = 0.025;
|
||||
light.shadow.radius = 2;
|
||||
light.shadow.camera.near = 1;
|
||||
light.shadow.camera.far = 220;
|
||||
shadowed_light_count++;
|
||||
} else {
|
||||
light.castShadow = false;
|
||||
}
|
||||
|
||||
this.interior_light_group_.add(light);
|
||||
this.interior_lights_.push(light);
|
||||
});
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
@ -160,40 +160,15 @@ beestat.component.scene.prototype.get_opening_center_z_ = function(group, openin
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a debug wireframe for an opening cutter.
|
||||
*
|
||||
* @param {THREE.Group} layer The debug layer.
|
||||
* @param {THREE.Mesh} cutter The cutter mesh.
|
||||
*/
|
||||
beestat.component.scene.prototype.add_opening_cutter_debug_ = function(layer, cutter) {
|
||||
const edges_geometry = new THREE.EdgesGeometry(cutter.geometry);
|
||||
const wireframe = new THREE.LineSegments(
|
||||
edges_geometry,
|
||||
new THREE.LineBasicMaterial({
|
||||
'color': 0xff7700
|
||||
})
|
||||
);
|
||||
wireframe.position.copy(cutter.position);
|
||||
wireframe.rotation.copy(cutter.rotation);
|
||||
wireframe.scale.copy(cutter.scale);
|
||||
wireframe.layers.set(beestat.component.scene.layer_visible);
|
||||
|
||||
layer.add(wireframe);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subtract opening cutters from wall meshes.
|
||||
*
|
||||
* @param {THREE.Group} walls_layer The wall mesh layer.
|
||||
* @param {object} floor_plan The floor plan data.
|
||||
* @param {THREE.Group=} opening_cutter_debug_layer Optional debug cutter layer.
|
||||
*/
|
||||
beestat.component.scene.prototype.apply_opening_cuts_ = function(
|
||||
walls_layer,
|
||||
floor_plan,
|
||||
opening_cutter_debug_layer
|
||||
floor_plan
|
||||
) {
|
||||
if (window.CSG === undefined || typeof window.CSG.subtract !== 'function') {
|
||||
return;
|
||||
@ -227,10 +202,6 @@ beestat.component.scene.prototype.apply_opening_cuts_ = function(
|
||||
return;
|
||||
}
|
||||
|
||||
if (opening_cutter_debug_layer !== undefined) {
|
||||
this.add_opening_cutter_debug_(opening_cutter_debug_layer, cutter);
|
||||
}
|
||||
|
||||
const cutter_box = new THREE.Box3().setFromObject(cutter);
|
||||
|
||||
group_wall_meshes.forEach(function(wall_mesh) {
|
||||
@ -280,50 +251,6 @@ beestat.component.scene.prototype.apply_opening_cuts_ = function(
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add red wireframe boxes to visualize opening placement in 3D.
|
||||
*
|
||||
* @param {THREE.Group} layer The layer to add opening debug to.
|
||||
* @param {object} group The floor plan group.
|
||||
*/
|
||||
beestat.component.scene.prototype.add_openings_debug_ = function(layer, group) {
|
||||
if (group.openings === undefined || group.openings.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wall_thickness = beestat.component.scene.wall_thickness;
|
||||
|
||||
group.openings.forEach(function(opening) {
|
||||
const opening_line = this.get_opening_line_params_(opening);
|
||||
const width = opening_line.width;
|
||||
const height = Math.max(1, Number(opening.height || this.get_opening_default_height_(opening.type)));
|
||||
const center_z = this.get_opening_center_z_(group, opening, height);
|
||||
|
||||
const geometry = new THREE.BoxGeometry(
|
||||
width,
|
||||
wall_thickness,
|
||||
height
|
||||
);
|
||||
|
||||
const edges_geometry = new THREE.EdgesGeometry(geometry);
|
||||
const wireframe = new THREE.LineSegments(
|
||||
edges_geometry,
|
||||
new THREE.LineBasicMaterial({
|
||||
'color': 0xff0000
|
||||
})
|
||||
);
|
||||
|
||||
wireframe.position.x = opening_line.center_x;
|
||||
wireframe.position.y = opening_line.center_y;
|
||||
wireframe.position.z = center_z;
|
||||
wireframe.rotation.z = opening_line.rotation_radians;
|
||||
wireframe.layers.set(beestat.component.scene.layer_visible);
|
||||
|
||||
layer.add(wireframe);
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add 3D opening fixtures.
|
||||
*
|
||||
|
||||
@ -670,15 +670,11 @@ beestat.component.scene.prototype.create_round_tree_ = function(height, max_diam
|
||||
const branch_axis = new THREE.Vector3(0, 0, -1);
|
||||
const foliage = new THREE.Group();
|
||||
foliage.userData.is_environment = true;
|
||||
const canopy_opacity = beestat.component.scene.debug_tree_canopy_opacity;
|
||||
const foliage_material = new THREE.MeshStandardMaterial({
|
||||
'color': 0x4f9f2f,
|
||||
'roughness': 0.82,
|
||||
'metalness': 0.0,
|
||||
'flatShading': true,
|
||||
'transparent': canopy_opacity < 1,
|
||||
'opacity': canopy_opacity,
|
||||
'depthWrite': canopy_opacity >= 1,
|
||||
'side': THREE.DoubleSide
|
||||
});
|
||||
const create_canopy_from_branch_function_ = function() {
|
||||
@ -1063,8 +1059,7 @@ beestat.component.scene.prototype.create_round_tree_ = function(height, max_diam
|
||||
if (has_foliage === true) {
|
||||
this.tree_branch_groups_.push(branches);
|
||||
}
|
||||
branches.visible =
|
||||
this.debug_.hide_tree_branches !== true;
|
||||
branches.visible = true;
|
||||
tree.add(branches);
|
||||
if (has_foliage === true) {
|
||||
tree.add(foliage);
|
||||
|
||||
@ -3,40 +3,6 @@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Set weather on the floor-plan appearance.
|
||||
*
|
||||
* @param {string} weather
|
||||
*
|
||||
* @return {beestat.component.scene}
|
||||
*/
|
||||
beestat.component.scene.prototype.set_weather = function(weather) {
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
if (floor_plan.data.appearance === undefined) {
|
||||
floor_plan.data.appearance = {};
|
||||
}
|
||||
const normalized_weather = beestat.weather.get_settings_(weather).condition;
|
||||
floor_plan.data.appearance.weather = normalized_weather;
|
||||
const weather_settings = {
|
||||
'cloud_density': beestat.weather.get_cloud_density(normalized_weather),
|
||||
'cloud_darkness': beestat.weather.get_cloud_darkness(normalized_weather),
|
||||
'rain_density': beestat.weather.get_rain_density(normalized_weather),
|
||||
'snow_density': beestat.weather.get_snow_density(normalized_weather),
|
||||
'lightning_frequency': beestat.weather.get_lightning_frequency(normalized_weather),
|
||||
'wind_speed': beestat.weather.get_wind_speed(normalized_weather)
|
||||
};
|
||||
this.set_scene_settings(weather_settings, {
|
||||
'rerender': false
|
||||
});
|
||||
|
||||
if (this.rendered_ === true) {
|
||||
this.update_();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get design count at density 1 for a weather channel.
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user