From fbdd8f75170f433cd99bcc5694afb95a00f90197 Mon Sep 17 00:00:00 2001 From: Martin Ender Date: Mon, 21 Feb 2022 21:56:18 +0100 Subject: [PATCH 1/2] Add crop transform --- src/js/parser.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/js/parser.js b/src/js/parser.js index 1a9168a7d..70ed65c60 100644 --- a/src/js/parser.js +++ b/src/js/parser.js @@ -622,6 +622,48 @@ PuzzleScriptParser.prototype.copySpriteMatrix = function() offset[1] += v[1]*parseInt(parts[2]) } break + case 'crop': + { + if (sprite.length == 0) + continue + + const sprite_size_key_index = this.metadata_keys.indexOf('sprite_size') + const [width, height] = this.metadata_values[sprite_size_key_index] + // Capture offset values because they get modified before these + // functions are evaluated. + const [offset_x, offset_y] = offset + const crop_functions = [ + ( m => offset_y <= -sprite[1].length ? ['.'] : Array.from(offset_y >= 0 ? m : m.slice(-offset_y))), // up + ( m => width <= offset_x ? ['.'] : Array.from(m, l => l.slice(0, width - offset_x))), // right + ( m => height <= offset_y ? ['.'] : Array.from(m.slice(0, height - offset_y))), // down + ( m => offset_x >= 0 + ? Array.from(m) + : offset_x <= -sprite[0].length + ? ['.'] + : Array.from(m, l => l.slice(-offset_x))), // left + ] + + if (parts.length > 1) + { + const crop_direction = expand_direction(parts[1], replaced_dir) + f = crop_functions[crop_direction] + + const offset_functions = [ + ( (x, y) => [x, y] ), // up + ( (x, y) => [x, y] ), // right + ( (x, y) => [x, Math.min(0, y)] ), // down + ( (x, y) => [Math.max(0, x), y] ), // left + ] + offset = offset_functions[crop_direction](...offset) + } + else + { + // Might be cleaner to define a separate function that performs the + // crop with only two slices (one per dimension). + f = (m => crop_functions[0](crop_functions[1](crop_functions[2](crop_functions[3](m))))) + offset = [Math.max(0, offset[0]), Math.min(0, offset[1])] + } + } default: } } @@ -848,7 +890,7 @@ PuzzleScriptParser.prototype.tokenInObjectsSection = function(is_start_of_line, } case 5: // copy spritematrix: transformations to apply { - const transform_match = stream.match(/\s*(shift:(?:left|up|right|down|[>v<^])(?::-?\d+)?|[-]|\||rot:(?:left|up|right|down|[>v<^]):(?:left|up|right|down|[>v<^])|translate:(?:left|up|right|down|[>v<^]):\d+)\s*/u, true) + const transform_match = stream.match(/\s*(shift:(?:left|up|right|down|[>v<^])(?::-?\d+)?|[-]|\||rot:(?:left|up|right|down|[>v<^]):(?:left|up|right|down|[>v<^])|translate:(?:left|up|right|down|[>v<^]):\d+|crop(?::[>v<^])?)\s*/u, true) if (transform_match === null) { this.logError('I do not understand this sprite transformation! Did you forget to insert a blank line between two object declarations?') From 7f27888514cfeaaa889759331468cfc71653a07c Mon Sep 17 00:00:00 2001 From: Martin Ender Date: Sat, 26 Feb 2022 00:05:15 +0100 Subject: [PATCH 2/2] Rework how the crop transform works (and call it trim) --- src/js/parser.js | 61 ++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/src/js/parser.js b/src/js/parser.js index 70ed65c60..c6af1469b 100644 --- a/src/js/parser.js +++ b/src/js/parser.js @@ -622,47 +622,36 @@ PuzzleScriptParser.prototype.copySpriteMatrix = function() offset[1] += v[1]*parseInt(parts[2]) } break - case 'crop': + case 'trim': { if (sprite.length == 0) - continue - - const sprite_size_key_index = this.metadata_keys.indexOf('sprite_size') - const [width, height] = this.metadata_values[sprite_size_key_index] - // Capture offset values because they get modified before these - // functions are evaluated. - const [offset_x, offset_y] = offset - const crop_functions = [ - ( m => offset_y <= -sprite[1].length ? ['.'] : Array.from(offset_y >= 0 ? m : m.slice(-offset_y))), // up - ( m => width <= offset_x ? ['.'] : Array.from(m, l => l.slice(0, width - offset_x))), // right - ( m => height <= offset_y ? ['.'] : Array.from(m.slice(0, height - offset_y))), // down - ( m => offset_x >= 0 - ? Array.from(m) - : offset_x <= -sprite[0].length - ? ['.'] - : Array.from(m, l => l.slice(-offset_x))), // left - ] - - if (parts.length > 1) { - const crop_direction = expand_direction(parts[1], replaced_dir) - f = crop_functions[crop_direction] - - const offset_functions = [ - ( (x, y) => [x, y] ), // up - ( (x, y) => [x, y] ), // right - ( (x, y) => [x, Math.min(0, y)] ), // down - ( (x, y) => [Math.max(0, x), y] ), // left - ] - offset = offset_functions[crop_direction](...offset) + const sprite_size_key_index = this.metadata_keys.indexOf('sprite_size') + const [width, height] = this.metadata_values[sprite_size_key_index] + sprite = Array(height).fill('0'.repeat(width)) } - else + + const trim_direction = expand_direction(parts[1], replaced_dir) + const trim_size = parts.length > 2 ? parseInt(parts[2]) : 1 + + switch (trim_direction) { - // Might be cleaner to define a separate function that performs the - // crop with only two slices (one per dimension). - f = (m => crop_functions[0](crop_functions[1](crop_functions[2](crop_functions[3](m))))) - offset = [Math.max(0, offset[0]), Math.min(0, offset[1])] + case 2: // down + offset[1] -= trim_size + break + case 3: // left + offset[0] += trim_size + break + default: + break } + + f = [ + ( m => m.length <= trim_size ? ['.'] : Array.from(m.slice(trim_size))), // up + ( m => m[0].length <= trim_size ? ['.'] : Array.from(m, l => l.slice(0, -trim_size))), // right + ( m => m.length <= trim_size ? ['.'] : Array.from(m.slice(0, -trim_size))), // down + ( m => m[0].length <= trim_size ? ['.'] : Array.from(m, l => l.slice(trim_size))), // left + ][trim_direction] } default: } @@ -890,7 +879,7 @@ PuzzleScriptParser.prototype.tokenInObjectsSection = function(is_start_of_line, } case 5: // copy spritematrix: transformations to apply { - const transform_match = stream.match(/\s*(shift:(?:left|up|right|down|[>v<^])(?::-?\d+)?|[-]|\||rot:(?:left|up|right|down|[>v<^]):(?:left|up|right|down|[>v<^])|translate:(?:left|up|right|down|[>v<^]):\d+|crop(?::[>v<^])?)\s*/u, true) + const transform_match = stream.match(/\s*(shift:(?:left|up|right|down|[>v<^])(?::-?\d+)?|[-]|\||rot:(?:left|up|right|down|[>v<^]):(?:left|up|right|down|[>v<^])|translate:(?:left|up|right|down|[>v<^]):\d+|trim:(?:left|up|right|down|[>v<^])(?::\d+)?)\s*/u, true) if (transform_match === null) { this.logError('I do not understand this sprite transformation! Did you forget to insert a blank line between two object declarations?')