1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

allow for border around selected area

This commit is contained in:
EmeraldBlock 2021-06-04 12:49:34 -05:00
parent 3f9229dc7c
commit 84c2aee7da

View File

@ -14,10 +14,14 @@ import { ORIGINAL_SPRITE_SCALE } from "../../../core/sprites";
import { getDeviceDPI } from "../../../core/dpi_manager"; import { getDeviceDPI } from "../../../core/dpi_manager";
import { HUDMassSelector } from "./mass_selector"; import { HUDMassSelector } from "./mass_selector";
import { clamp } from "../../../core/utils"; import { clamp } from "../../../core/utils";
import { CHUNK_OVERLAY_RES } from "../../map_chunk_view";
const logger = createLogger("screenshot_exporter"); const logger = createLogger("screenshot_exporter");
const MAX_CANVAS_DIMS = 16384; const MAX_CANVAS_DIMS = 16384;
// should be odd so that the centers of tiles are rendered
// as pixels per tile must be a multiple of this
const TARGET_INVERSE_BORDER = 3;
const screenshotQualities = [ const screenshotQualities = [
{ {
@ -126,6 +130,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
qualityInput.getValue(), qualityInput.getValue(),
overlayInput.getValue(), overlayInput.getValue(),
layerInput.getValue(), layerInput.getValue(),
!!bounds,
bounds bounds
), ),
this this
@ -134,15 +139,16 @@ export class HUDScreenshotExporter extends BaseHUDPart {
/** /**
* Renders a screenshot of the entire base as closely as possible to the ingame camera * Renders a screenshot of the entire base as closely as possible to the ingame camera
* @param {number} resolution * @param {number} targetResolution
* @param {boolean} overlay * @param {boolean} overlay
* @param {boolean} wiresLayer * @param {boolean} wiresLayer
* @param {Rectangle?} bounds * @param {boolean} allowBorder
* @param {Rectangle?} tileBounds
*/ */
doExport(resolution, overlay, wiresLayer, bounds) { doExport(targetResolution, overlay, wiresLayer, allowBorder, tileBounds) {
logger.log("Starting export ..."); logger.log("Starting export ...");
if (!bounds) { if (!tileBounds) {
// Find extends // Find extends
const staticEntities = this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent); const staticEntities = this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent);
@ -163,32 +169,42 @@ export class HUDScreenshotExporter extends BaseHUDPart {
maxTile.x = Math.ceil(maxTile.x / globalConfig.mapChunkSize) * globalConfig.mapChunkSize; maxTile.x = Math.ceil(maxTile.x / globalConfig.mapChunkSize) * globalConfig.mapChunkSize;
maxTile.y = Math.ceil(maxTile.y / globalConfig.mapChunkSize) * globalConfig.mapChunkSize; maxTile.y = Math.ceil(maxTile.y / globalConfig.mapChunkSize) * globalConfig.mapChunkSize;
bounds = Rectangle.fromTwoPoints(minTile, maxTile); tileBounds = Rectangle.fromTwoPoints(minTile, maxTile);
} }
// if the desired pixels per tile is too small, we do not create a border
// so that we have more valid values for pixels per tile
// we do not create a border for map view since there is no sprite overflow
const border =
allowBorder &&
!overlay &&
targetResolution / (Math.max(tileBounds.w, tileBounds.h) + 2 / TARGET_INVERSE_BORDER) >=
3 * TARGET_INVERSE_BORDER;
const bounds = border ? tileBounds.expandedInAllDirections(1 / TARGET_INVERSE_BORDER) : tileBounds;
logger.log("Bounds:", bounds); logger.log("Bounds:", bounds);
const maxDimensions = Math.max(bounds.w, bounds.h); const maxDimensions = Math.max(bounds.w, bounds.h);
// at least 3 pixels per tile, for bearable quality
// at most the resolution of the assets, to not be excessive
const clamped = clamp(
targetResolution / (maxDimensions + (border ? 2 / 3 : 0)),
3,
globalConfig.assetsDpi * globalConfig.tileSize
);
// 1 is a fake value since it behaves the same as a border width of 0
const inverseBorder = border ? TARGET_INVERSE_BORDER : 1;
const tileSizePixels = overlay const tileSizePixels = overlay
? // we want multiple of 3 pixels per tile, since the map mode buildings are 3x3 pixels ? // we floor to the nearest multiple of the map view tile resolution
// higher resolutions are to render resource patch icons Math.floor(clamped / CHUNK_OVERLAY_RES) * CHUNK_OVERLAY_RES || CHUNK_OVERLAY_RES
clamp( : // we floor to the nearest odd multiple so that the center of each building is rendered
Math.floor(resolution / maxDimensions / 3) * 3, Math.floor((clamped + inverseBorder) / (2 * inverseBorder)) * (2 * inverseBorder) -
3, inverseBorder || inverseBorder;
Math.floor((globalConfig.assetsDpi * globalConfig.tileSize) / 3) * 3
)
: // we want odd integer pixels per tile, so that center of tile is rendered
// at least 3 pixels per tile, for bearable quality
// at most the resolution of the assets, to not be excessive
clamp(
Math.floor((resolution / maxDimensions + 1) / 2) * 2 - 1,
3,
globalConfig.assetsDpi * globalConfig.tileSize
);
logger.log("Pixels per tile:", tileSizePixels); logger.log("Pixels per tile:", tileSizePixels);
if (tileSizePixels * maxDimensions > MAX_CANVAS_DIMS) { if (Math.round(tileSizePixels * maxDimensions) > MAX_CANVAS_DIMS) {
logger.error("Maximum canvas size exceeded, aborting"); logger.error("Maximum canvas size exceeded, aborting");
// @TODO: translation (T.dialogs.exportScreenshotFail.title) (T.dialogs.exportScreenshotFail.text) // @TODO: translation (T.dialogs.exportScreenshotFail.title) (T.dialogs.exportScreenshotFail.text)
this.root.hud.parts.dialogs.showInfo("Too large", "The base is too large to render, sorry!"); this.root.hud.parts.dialogs.showInfo("Too large", "The base is too large to render, sorry!");
@ -210,11 +226,15 @@ export class HUDScreenshotExporter extends BaseHUDPart {
} }
logger.log("Allocating buffer, if the factory grew too big it will crash here"); logger.log("Allocating buffer, if the factory grew too big it will crash here");
const [canvas, context] = makeOffscreenBuffer(bounds.w * tileSizePixels, bounds.h * tileSizePixels, { const [canvas, context] = makeOffscreenBuffer(
smooth: true, Math.round(bounds.w * tileSizePixels),
reusable: false, Math.round(bounds.h * tileSizePixels),
label: "export-buffer", {
}); smooth: true,
reusable: false,
label: "export-buffer",
}
);
logger.log("Got buffer, rendering now ..."); logger.log("Got buffer, rendering now ...");
const visibleRect = bounds.allScaled(globalConfig.tileSize); const visibleRect = bounds.allScaled(globalConfig.tileSize);