116 lines
5.2 KiB
JavaScript
116 lines
5.2 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
const root = window.PixelIslandModules ||= {};
|
|
const utils = root.CoreUtils || {};
|
|
const clamp = utils.clamp || ((value, min, max) => Math.max(min, Math.min(max, value)));
|
|
const lerp = utils.lerp || ((a, b, t) => a + (b - a) * t);
|
|
const mod = utils.mod || ((n, m) => ((n % m) + m) % m);
|
|
|
|
function smooth(t) {
|
|
const n = clamp(t, 0, 1);
|
|
return n * n * (3 - 2 * n);
|
|
}
|
|
|
|
function getShadowForMinute(minute) {
|
|
const m = clamp(Number(minute) || 0, 0, 10);
|
|
let dirX = -0.9;
|
|
let length = 1.2;
|
|
let alpha = 0;
|
|
let scaleY = 0.26;
|
|
|
|
if (m < 0.65) {
|
|
const t = smooth(m / 0.65);
|
|
dirX = lerp(0.42, 0.18, t);
|
|
length = lerp(1.05, 0.92, t);
|
|
alpha = lerp(0.12, 0.0, t);
|
|
scaleY = lerp(0.22, 0.18, t);
|
|
} else if (m < 1.35) {
|
|
const t = smooth((m - 0.65) / 0.70);
|
|
dirX = lerp(-1.05, -0.82, t);
|
|
length = lerp(1.38, 1.12, t);
|
|
alpha = lerp(0.0, 0.27, t);
|
|
scaleY = lerp(0.22, 0.27, t);
|
|
} else if (m < 5.65) {
|
|
const t = smooth((m - 1.35) / 4.30);
|
|
const elevation = Math.sin(t * Math.PI);
|
|
dirX = lerp(-0.82, 0.98, t);
|
|
length = lerp(1.12, 1.34, t) - elevation * 0.48;
|
|
alpha = lerp(0.27, 0.20, elevation);
|
|
scaleY = 0.24 + 0.06 * (1 - elevation);
|
|
} else if (m < 6.40) {
|
|
const t = smooth((m - 5.65) / 0.75);
|
|
dirX = lerp(0.98, 1.08, t);
|
|
length = lerp(1.34, 1.56, t);
|
|
alpha = lerp(0.20, 0.0, t);
|
|
scaleY = lerp(0.28, 0.20, t);
|
|
} else if (m < 7.25) {
|
|
const t = smooth((m - 6.40) / 0.85);
|
|
dirX = lerp(0.20, -0.36, t);
|
|
length = lerp(0.92, 1.08, t);
|
|
alpha = lerp(0.0, 0.12, t);
|
|
scaleY = lerp(0.18, 0.23, t);
|
|
} else if (m < 9.20) {
|
|
const t = smooth((m - 7.25) / 1.95);
|
|
dirX = lerp(-0.36, -0.58, t);
|
|
length = lerp(1.08, 1.18, t);
|
|
alpha = 0.12;
|
|
scaleY = 0.23;
|
|
} else {
|
|
const t = smooth((m - 9.20) / 0.80);
|
|
dirX = lerp(-0.58, 0.42, t);
|
|
length = lerp(1.18, 1.05, t);
|
|
alpha = lerp(0.12, 0.0, t);
|
|
scaleY = lerp(0.23, 0.18, t);
|
|
}
|
|
|
|
return { dirX, length, skewX: dirX * (0.72 + 0.32 * length), scaleY, alpha };
|
|
}
|
|
|
|
function getPhase(options) {
|
|
const { dayMs, now, dayNightEnabled, mixHex } = options;
|
|
if (dayNightEnabled === false) {
|
|
return { key: 'day', label: 'Day', progress: 0.25, sky: '#86d5ff', darkness: 0, darkOverlay: 'rgba(12, 19, 45, 0)', tint: 'rgba(255,255,255,0)', tintAlpha: 0, shadow: getShadowForMinute(3) };
|
|
}
|
|
const t = mod(now || Date.now(), dayMs);
|
|
const minute = t / 60000;
|
|
const stops = [
|
|
{ at: 0.00, key: 'preDawn', label: 'Night', sky: '#17254e', darkness: 0.52, tint: [22, 28, 66, 0.10], overlay: [12, 19, 45] },
|
|
{ at: 0.65, key: 'dawn', label: 'Morning', sky: '#5969aa', darkness: 0.30, tint: [120, 100, 150, 0.10], overlay: [40, 43, 78] },
|
|
{ at: 1.35, key: 'morning', label: 'Morning', sky: '#f6b16b', darkness: 0.12, tint: [255, 195, 126, 0.13], overlay: [114, 64, 36] },
|
|
{ at: 2.15, key: 'day', label: 'Day', sky: '#8ad8ff', darkness: 0.00, tint: [255, 255, 255, 0.00], overlay: [12, 19, 45] },
|
|
{ at: 4.75, key: 'day', label: 'Day', sky: '#8ad8ff', darkness: 0.00, tint: [255, 255, 255, 0.00], overlay: [12, 19, 45] },
|
|
{ at: 5.65, key: 'evening', label: 'Evening', sky: '#ffa153', darkness: 0.07, tint: [255, 166, 88, 0.10], overlay: [130, 48, 18] },
|
|
{ at: 6.40, key: 'evening', label: 'Evening', sky: '#d55a2d', darkness: 0.20, tint: [255, 118, 62, 0.17], overlay: [118, 42, 18] },
|
|
{ at: 7.25, key: 'night', label: 'Night', sky: '#1b2a58', darkness: 0.46, tint: [32, 40, 82, 0.07], overlay: [12, 19, 45] },
|
|
{ at: 9.20, key: 'night', label: 'Night', sky: '#132247', darkness: 0.58, tint: [16, 24, 58, 0.10], overlay: [12, 19, 45] },
|
|
{ at: 10.00, key: 'preDawn', label: 'Night', sky: '#17254e', darkness: 0.52, tint: [22, 28, 66, 0.10], overlay: [12, 19, 45] }
|
|
];
|
|
let a = stops[0], b = stops[1];
|
|
for (let i = 0; i < stops.length - 1; i++) {
|
|
if (minute >= stops[i].at && minute < stops[i + 1].at) {
|
|
a = stops[i];
|
|
b = stops[i + 1];
|
|
break;
|
|
}
|
|
}
|
|
const eased = smooth((minute - a.at) / Math.max(0.0001, b.at - a.at));
|
|
const tint = a.tint.map((value, i) => lerp(value, b.tint[i], eased));
|
|
const overlay = a.overlay.map((value, i) => lerp(value, b.overlay[i], eased));
|
|
const darkness = lerp(a.darkness, b.darkness, eased);
|
|
const dominantKey = darkness >= 0.34 ? 'night' : (a.key === 'evening' || b.key === 'evening' ? 'evening' : (a.key === 'morning' || b.key === 'morning' || a.key === 'dawn' || b.key === 'dawn' ? 'morning' : 'day'));
|
|
return {
|
|
key: dominantKey,
|
|
label: dominantKey === 'night' ? 'Night' : dominantKey === 'evening' ? 'Evening' : dominantKey === 'morning' ? 'Morning' : 'Day',
|
|
progress: t / dayMs,
|
|
sky: mixHex(a.sky, b.sky, eased),
|
|
darkness,
|
|
darkOverlay: `rgba(${Math.round(overlay[0])}, ${Math.round(overlay[1])}, ${Math.round(overlay[2])}, ${darkness.toFixed(3)})`,
|
|
tint: `rgba(${Math.round(tint[0])}, ${Math.round(tint[1])}, ${Math.round(tint[2])}, ${tint[3].toFixed(3)})`,
|
|
tintAlpha: tint[3],
|
|
shadow: getShadowForMinute(minute)
|
|
};
|
|
}
|
|
|
|
root.Lighting = { getPhase, getShadowForMinute };
|
|
})();
|