Skip to content
Snippets Groups Projects
Commit ee478015 authored by xao's avatar xao
Browse files

Refactored bindings to make it easier to add - added canvas refresh on save-load

parent 4eb4fabc
No related branches found
No related tags found
3 merge requests!2821Weather/sky overhaul and Great Hawk expansion,!2804Combat finalisations,!2739Replacing hardcoded clothing logic in preparation for overwear.
/*
Bind a value to the sky canvas.
If the value changes - it will update the specified layer(s)
*/
setup.WeatherBindings = {
save: {
variable: () => T.saveLoaded,
layers: ["all"],
},
time: {
variable: () => Time.date.timeStamp,
layers: ["all"],
},
weather: {
variable: () => Weather.name,
layers: ["clouds", "cirrusClouds", "overcastClouds"],
},
precipitation: {
variable: () => Weather.name,
layers: ["precipitation"],
},
location: {
variable: () => V.location,
layers: ["location"],
},
bus: {
variable: () => V.bus,
layers: ["location"],
},
bloodmoon: {
variable: () => Weather.bloodMoon,
layers: ["location"],
},
snow: {
variable: () => Weather.isSnow,
layers: ["location"],
},
dayState: {
variable: () => Time.dayState,
layers: ["location"],
},
lightsOn: {
variable: () => Weather.lightsOn,
layers: ["location"],
},
};
Weather.Observables = (() => {
// Schedules the updates so that the same layers don't update multiple times by different bindings
class UpdateScheduler {
constructor() {
this.updates = new Set();
this.scheduled = false;
}
scheduleUpdate(update) {
this.updates.add(update);
if (!this.scheduled) {
this.scheduled = true;
Promise.resolve().then(() => this.executeUpdates());
}
}
executeUpdates() {
this.updates.forEach(update => update());
this.updates.clear();
this.scheduled = false;
}
}
const scheduler = new UpdateScheduler();
const observables = {};
Object.entries(setup.WeatherBindings).forEach(([key, config]) => {
const observable = new ObservableValue(null);
observables[key] = observable;
observable.subscribe(value => {
if (value === undefined) return;
if (config.layers.includes("all")) {
scheduler.scheduleUpdate(() => {
Weather.Sky.updateOrbits();
Weather.Sky.updateFade();
Weather.Sky.updateTooltip();
Weather.Sky.drawLayers();
});
} else {
scheduler.scheduleUpdate(async () => {
for (const layer of config.layers) {
await Weather.Sky.getLayer(layer).init();
}
Weather.Sky.drawLayers(...config.layers);
});
}
});
});
Weather.Sky.loaded.subscribe(() => {
Weather.Sky.updateTooltip();
$(document).on(":passageend", () => {
Object.keys(observables).forEach(key => {
observables[key].value = setup.WeatherBindings[key].variable();
});
if (Weather.Sky.loaded.value) Weather.Sky.updateTooltip();
});
});
return {};
})();
......@@ -13,6 +13,7 @@ WeatherEffects.create({
this.stopAnimation = () => this.animation?.stop();
this.startAnimation = () => this.animation?.start();
this.stopAnimation();
const scaledFrameWidth = this.frameWidth * setup.SkySettings.scale;
const scaledFrameHeight = this.images.precipitation.height;
const numFrames = this.images.precipitation.width / scaledFrameWidth;
......@@ -25,7 +26,6 @@ WeatherEffects.create({
const precipitationSheet = new Weather.Sky.Canvas(scaledFrameWidth * numFrames * spriteColumns, scaledFrameHeight * spriteRows);
const precipitationFrame = new Weather.Sky.Canvas(scaledFrameWidth * spriteColumns, scaledFrameHeight * spriteRows);
for (let i = 0; i < numFrames; i++) {
precipitationFrame.clear();
......@@ -40,13 +40,33 @@ WeatherEffects.create({
const frameX = i * scaledFrameWidth;
if (x + scaledFrameWidth > 0 && x < precipitationFrame.element.width) {
precipitationFrame.ctx.drawImage(this.images.precipitation, frameX, 0, scaledFrameWidth, this.images.precipitation.height, x, y, scaledFrameWidth, scaledFrameHeight);
precipitationFrame.ctx.drawImage(
this.images.precipitation,
frameX,
0,
scaledFrameWidth,
this.images.precipitation.height,
x,
y,
scaledFrameWidth,
scaledFrameHeight
);
}
}
}
const destX = i * scaledFrameWidth * spriteColumns;
precipitationSheet.ctx.drawImage(precipitationFrame.element, 0, 0, precipitationFrame.element.width, precipitationFrame.element.height, destX, 0, precipitationFrame.element.width, precipitationFrame.element.height);
precipitationSheet.ctx.drawImage(
precipitationFrame.element,
0,
0,
precipitationFrame.element.width,
precipitationFrame.element.height,
destX,
0,
precipitationFrame.element.width,
precipitationFrame.element.height
);
}
this.frameTotalWidth = precipitationSheet.element.width / numFrames;
......@@ -56,6 +76,15 @@ WeatherEffects.create({
draw() {
if (!this.animation.enabled) this.startAnimation();
this.canvas.ctx.globalAlpha = this.alpha;
this.animation.draw(this.canvas.ctx, 0, 0, this.canvas.element.width, this.canvas.element.height, this.canvas.element.width, this.canvas.element.height, this.frameTotalWidth);
this.animation.draw(
this.canvas.ctx,
0,
0,
this.canvas.element.width,
this.canvas.element.height,
this.canvas.element.width,
this.canvas.element.height,
this.frameTotalWidth
);
},
});
/* eslint-disable no-undef */
/* eslint-disable no-unused-expressions */
/* eslint-disable no-unused-vars */
/* eslint-disable prettier/prettier */
Weather.Observables = (() => {
class UpdateScheduler {
constructor() {
this.updates = new Set();
this.scheduled = false;
}
scheduleUpdate(update) {
this.updates.add(update);
if (!this.scheduled) {
this.scheduled = true;
Promise.resolve().then(() => this.executeUpdates());
}
}
executeUpdates() {
this.updates.forEach(update => update());
this.updates.clear();
this.scheduled = false;
}
}
const observables = ObservableValue.fromObject({
location: null,
bus: null,
time: null,
weather: null,
precipitation: null,
precipitationIntensity: null,
snow: null,
bloodMoon: null,
//Location conditions
dayState: null,
lightsOn: null,
});
// Prevents multiple of the same update function to execute at the same time
const scheduler = new UpdateScheduler();
Weather.Sky.loaded.subscribe( () => {
Weather.Sky.updateTooltip();
$(document).on(":passageend", () => {
observables.location.value = V.location;
observables.bus.value = V.bus;
observables.time.value = Time.date.timeStamp;
observables.weather.value = Weather.name;
observables.precipitation.value = Weather.precipitation;
observables.precipitationIntensity.value = Weather.precipitationIntensity;
observables.snow.value = Weather.isSnow;
observables.bloodMoon.value = Weather.bloodMoon;
observables.dayState.value = Time.dayState;
observables.lightsOn.value = Weather.lightsOn;
if (Weather.Sky.loaded.value) Weather.Sky.updateTooltip();
});
const updateLocation = async () => {
await Weather.Sky.getLayer("location").init();
Weather.Sky.drawLayers("location");
};
const updateWeather = async () => {
await Weather.Sky.getLayer("clouds").init();
await Weather.Sky.getLayer("cirrusClouds").init();
await Weather.Sky.getLayer("overcastClouds").init();
Weather.Sky.drawLayers("clouds", "cirrusClouds", "overcastClouds");
};
const updatePrecipitation = async () => {
Weather.Sky.getLayer("precipitation").effects[0].stopAnimation();
Weather.Sky.drawLayers("precipitation");
};
const drawAll = () => {
Weather.Sky.updateOrbits();
Weather.Sky.updateFade();
Weather.Sky.updateTooltip();
Weather.Sky.drawLayers();
};
/* LOCATION */
observables.location.subscribe(() => scheduler.scheduleUpdate(updateLocation));
observables.bus.subscribe(() => scheduler.scheduleUpdate(updateLocation));
observables.bloodMoon.subscribe(() => scheduler.scheduleUpdate(updateLocation));
observables.snow.subscribe(() => scheduler.scheduleUpdate(updateLocation));
observables.dayState.subscribe(() => scheduler.scheduleUpdate(updateLocation));
observables.lightsOn.subscribe(() => scheduler.scheduleUpdate(updateLocation));
/* WEATHER */
observables.weather.subscribe(() => scheduler.scheduleUpdate(updateWeather));
observables.precipitation.subscribe(() => scheduler.scheduleUpdate(updatePrecipitation));
observables.precipitationIntensity.subscribe(() => scheduler.scheduleUpdate(updatePrecipitation));
/* TIME */
observables.time.subscribe(() => scheduler.scheduleUpdate(drawAll));
});
return {};
})();
......@@ -39,6 +39,7 @@
<<updatehistorycontrols>>
<<set _preventUpdate to true>> /*prevent rewriting autosaves */
<<set _saveLoaded to true>>
<<setFont>>
<<run zoom($options.zoom)>>
<<run syncFavourites()>>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment