diff --git a/mod_examples/README.md b/mod_examples/README.md index b8e501c8..2eccb1e2 100644 --- a/mod_examples/README.md +++ b/mod_examples/README.md @@ -40,6 +40,7 @@ To get into shapez.io modding, I highly recommend checking out all of the exampl | [modify_existing_building.js](modify_existing_building.js) | Makes the rotator building always unlocked and adds a new statistic to the building panel | Modifying a builtin building, replacing builtin methods | | [modify_ui.js](modify_ui.js) | Shows how to add custom UI elements to builtin game states (the Main Menu in this case) | Extending builtin UI states, Adding CSS | | [pasting.js](pasting.js) | Shows a dialog when pasting text in the game | Listening to paste events | +| [smooth_zooming.js](smooth_zooming.js) | Allows to smoothly zoom in and out | Keybindings, overriding methods | | [sandbox.js](sandbox.js) | Makes blueprints free and always unlocked | Overriding builtin methods | ### Advanced Examples diff --git a/mod_examples/smooth_zooming.js b/mod_examples/smooth_zooming.js new file mode 100644 index 00000000..94254f2d --- /dev/null +++ b/mod_examples/smooth_zooming.js @@ -0,0 +1,58 @@ +// @ts-nocheck +const METADATA = { + website: "https://tobspr.io", + author: "tobspr", + name: "Smooth Zoom", + version: "1", + id: "smooth_zoom", + description: "Allows to zoom in and out smoothly, also disables map overview", + minimumGameVersion: ">=1.5.0", +}; + +class Mod extends shapez.Mod { + init() { + this.modInterface.registerIngameKeybinding({ + id: "smooth_zoom_zoom_in", + keyCode: shapez.keyToKeyCode("1"), + translation: "Zoom In (use with SHIFT)", + modifiers: { + shift: true, + }, + handler: root => { + root.camera.setDesiredZoom(5); + return shapez.STOP_PROPAGATION; + }, + }); + this.modInterface.registerIngameKeybinding({ + id: "smooth_zoom_zoom_out", + keyCode: shapez.keyToKeyCode("0"), + translation: "Zoom Out (use with SHIFT)", + modifiers: { + shift: true, + }, + handler: root => { + root.camera.setDesiredZoom(0.1); + return shapez.STOP_PROPAGATION; + }, + }); + + this.modInterface.extendClass(shapez.Camera, ({ $old }) => ({ + internalUpdateZooming(now, dt) { + if (!this.currentlyPinching && this.desiredZoom !== null) { + const diff = this.zoomLevel - this.desiredZoom; + if (Math.abs(diff) > 0.0001) { + const speed = 0.0005; + let step = Math.sign(diff) * Math.min(speed, Math.abs(diff)); + const pow = 1 / 2; + this.zoomLevel = Math.pow(Math.pow(this.zoomLevel, pow) - step, 1 / pow); + } else { + this.zoomLevel = this.desiredZoom; + this.desiredZoom = null; + } + } + }, + })); + + shapez.globalConfig.mapChunkOverviewMinZoom = -1; + } +} diff --git a/src/css/main.scss b/src/css/main.scss index 4850e3df..764347ac 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -132,17 +132,7 @@ $zindex: 100; } body.uiHidden { - .ingame_buildingsToolbar, - #ingame_HUD_PlacementHints, - #ingame_HUD_GameMenu, - #ingame_HUD_PinnedShapes, - #ingame_HUD_PuzzleBackToMenu, - #ingame_HUD_PuzzleNextPuzzle, - #ingame_HUD_PuzzleEditorReview, - #ingame_HUD_Notifications, - #ingame_HUD_TutorialHints, - #ingame_HUD_Waypoints, - #ingame_HUD_Waypoints_Hint { + > div { display: none !important; } } diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index 3eaf1f8a..1d6bffb9 100644 --- a/src/js/core/buffer_maintainer.js +++ b/src/js/core/buffer_maintainer.js @@ -68,7 +68,11 @@ export class BufferMaintainer { // Filter sub cache subCache.forEach((cacheEntry, subKey) => { - if (cacheEntry.lastUse < minIteration) { + if ( + cacheEntry.lastUse < minIteration || + // @ts-ignore + cacheEntry.canvas._contextLost + ) { unusedSubKeys.push(subKey); freeCanvas(cacheEntry.canvas); ++deletedKeys; diff --git a/src/js/core/buffer_utils.js b/src/js/core/buffer_utils.js index 310c315f..0048b214 100644 --- a/src/js/core/buffer_utils.js +++ b/src/js/core/buffer_utils.js @@ -161,7 +161,20 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe // Initial state context.save(); + + canvas.addEventListener("webglcontextlost", () => { + console.warn("canvas::webglcontextlost", canvas); + // @ts-ignore + canvas._contextLost = true; + }); + canvas.addEventListener("contextlost", () => { + console.warn("canvas::contextlost", canvas); + // @ts-ignore + canvas._contextLost = true; + }); } + // @ts-ignore + canvas._contextLost = false; // @ts-ignore canvas.label = label; diff --git a/src/js/core/config.js b/src/js/core/config.js index 0ee90cb5..f02366f4 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -119,7 +119,8 @@ export const globalConfig = { currentDiscount: { amount: 50, - until: Date.parse("April 25 2022 23:59 +2:00"), + from: Date.parse("May 23 2022 17:00 +2:00"), + until: Date.parse("May 30 2022 23:59 +2:00"), active: false, // computed later }, @@ -170,4 +171,6 @@ if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { } globalConfig.currentDiscount.active = - !G_IS_STANDALONE && new Date().getTime() < globalConfig.currentDiscount.until; + !G_IS_STANDALONE && + new Date().getTime() < globalConfig.currentDiscount.until && + new Date().getTime() > globalConfig.currentDiscount.from; diff --git a/src/js/game/map_view.js b/src/js/game/map_view.js index c6078ea9..6a940a60 100644 --- a/src/js/game/map_view.js +++ b/src/js/game/map_view.js @@ -225,6 +225,12 @@ export class MapView extends BaseMap { const dpi = this.backgroundCacheDPI; parameters.context.scale(1 / dpi, 1 / dpi); + // @ts-ignore + if (this.cachedBackgroundCanvas._contextLost) { + freeCanvas(this.cachedBackgroundCanvas); + this.internalInitializeCachedBackgroundCanvases(); + } + parameters.context.fillStyle = parameters.context.createPattern( this.cachedBackgroundCanvas, "repeat"