content/hifi-content/alan/dev/Scripts/moodLights.js
2022-02-13 20:41:08 +01:00

201 lines
6.1 KiB
JavaScript

// moodLight.js
//
// This script can be tested in Interface, but should ultimately run as an AC script.
// Tweens serveral set moodlights.
//
// Created by Thijs Wenker on September 21, 2016.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Light schedules have the Cycle Percentage as key and the color as value
var DEFAULT_LIGHT_SCHEDULE = {
0.0: {red: 247, green: 175, blue: 42},
0.3334: {red: 250, green: 20, blue: 112},
0.6667: {red: 0, green: 128, blue: 102},
};
var DEFAULT_LIGHT_SCHEDULE_2 = {
0.0: {red: 199, green: 43, blue: 0},
0.3334: {red: 107, green: 3, blue: 148},
0.6667: {red: 0, green: 13, blue: 150},
};
// Setup your mood-light below
var moodLights = [
{
properties: {
name: 'color Debug',
position: {
x: -27.46241426467896,
y: 8.558837890625,
z: -32.07110595703125
},
type: 'Sphere'
},
schedule: DEFAULT_LIGHT_SCHEDULE
},
{
properties: {
cutoff: 90,
dimensions: {
x: 59.687240600585938,
y: 59.687240600585938,
z: 59.687240600585938
},
falloffRadius: 100,
intensity: 2.2999999523162842,
name: 'RoatingLight1',
position: {
x: -4.2,
y: 8.6062,
z: -18.0129
},
rotation: {
w: 1,
x: -1.52587890625e-05,
y: -1.52587890625e-05,
z: -1.52587890625e-05
},
type: 'Light'
},
schedule: DEFAULT_LIGHT_SCHEDULE
},
{
properties: {
cutoff: 90,
dimensions: {
x: 68.6043701171875,
y: 68.6043701171875,
z: 68.6043701171875
},
falloffRadius: 10,
intensity: 15,
name: 'RotatingLight2',
position: {
x: -4.2163,
y: 4.6453,
z: -18
},
rotation: {
w: 1,
x: -1.52587890625e-05,
y: -1.52587890625e-05,
z: -1.52587890625e-05
},
type: 'Light'
},
schedule: DEFAULT_LIGHT_SCHEDULE_2
}
];
// The time it takes for a cycle to 100% complete (1.0)
var CYCLE_SECONDS = 100; // 5 minutes
// MAX_INACTIVE_SECONDS will contineous be added with the age to the lifetime, when the script is inactive the lights will disappear
var MAX_INACTIVE_SECONDS = 10;
// How frequently do we send out updates per second? :
var UPDATE_FREQUENCY = 50; //Hz
const MILLISECONDS_PER_SECOND = 1000;
function getNearestArrayValues(array, goal, continuous) {
var floorValue = null, ceilValue = null;
array.forEach(function(entry) {
if ((floorValue === null || entry > floorValue) && entry <= goal) {
floorValue = entry;
}
if ((ceilValue === null || entry < ceilValue) && entry >= goal) {
ceilValue = entry;
}
});
if (continuous && floorValue === null) {
floorValue = Math.max.apply(Math, array);
}
if (continuous && ceilValue === null) {
ceilValue = Math.min.apply(Math, array);
}
return {
floor: floorValue,
ceil: ceilValue
};
}
function tweeningPercentage(min, max, current) {
var currentOffset = (current >= min ? (current - min) : (current + 1 - min));
var dividerOffset = max - min;
if (min > max) {
dividerOffset += 1;
}
return currentOffset / dividerOffset;
}
function mix(valueA, valueB, mixPercentage) {
return valueA + mixPercentage * (valueB - valueA);
}
function MoodLight(properties, schedule) {
this.properties = properties;
this.schedule = schedule;
this.properties['lifetime'] = MAX_INACTIVE_SECONDS;
this.entityID = Entities.addEntity(this.properties);
this.creationSeconds = Date.now() / MILLISECONDS_PER_SECOND;
}
MoodLight.prototype = {
properties: null,
schedule: null,
entityID: null,
creationSeconds: null,
getCurrentColor: function() {
var percentageOfCycle = ((Date.now() / MILLISECONDS_PER_SECOND) % CYCLE_SECONDS) / CYCLE_SECONDS;
var minMaxKey = getNearestArrayValues(Object.keys(this.schedule), percentageOfCycle, true);
var minColor = this.schedule[minMaxKey.floor];
var maxColor = this.schedule[minMaxKey.ceil];
var mixPercentage = tweeningPercentage(minMaxKey.floor, minMaxKey.ceil, percentageOfCycle);
var mixedColor = {
red: mix(minColor.red, maxColor.red, mixPercentage),
green: mix(minColor.green, maxColor.green, mixPercentage),
blue: mix(minColor.blue, maxColor.blue, mixPercentage),
};
//print((percentageOfCycle * 100).toFixed(3) + '% ' + JSON.stringify(minColor) + ' mix ( ' + (mixPercentage * 100).toFixed(3) + '% ' + ' ) ' + JSON.stringify(maxColor) + ' = ' + JSON.stringify(mixedColor));
return mixedColor;
},
getNewLifetime: function() {
return ((Date.now() / MILLISECONDS_PER_SECOND) -this.creationSeconds) + MAX_INACTIVE_SECONDS;
},
update: function() {
var newProperties = {};
newProperties['lifetime'] = this.getNewLifetime();
newProperties['color'] = this.getCurrentColor();
Entities.editEntity(this.entityID, newProperties);
}
};
var moodLightInstances = [];
var initialized = false;
function update(deltaTime) {
if (!initialized) {
if (Entities.serversExist() && Entities.canRez()) {
Entities.setPacketsPerSecond(60000);
moodLights.forEach(function(moodLight) {
moodLightInstances.push(new MoodLight(moodLight.properties, moodLight.schedule));
});
initialized = true;
Script.update.disconnect(update);
}
}
}
Script.update.connect(update);
Script.setInterval(function() {
moodLightInstances.forEach(function(moodLight) {
moodLight.update();
});
}, MILLISECONDS_PER_SECOND / UPDATE_FREQUENCY);