diff --git a/.tests/parse/axes/axes_parser.test.lua b/.tests/parse/axes/axes_parser.test.lua index 00546cd..a698438 100644 --- a/.tests/parse/axes/axes_parser.test.lua +++ b/.tests/parse/axes/axes_parser.test.lua @@ -96,6 +96,15 @@ describe("parse_axes", function() assert.are.same(Vector3.new(40, 77, 99), maxv) end) + it("should infer that directions before a value are connected to that value", function() + local minv, maxv = parse_axes({ + "xy", "-x", "5" + }, facing_dirs.z_neg) + assert.is.truthy(minv) + assert.are.same(Vector3.new(-5, 0, 0), minv) + assert.are.same(Vector3.new(5, 5, 0), maxv) + end) + it("should return 2 0,0,0 vectors if no input", function() local minv, maxv = parse_axes({ -- No input diff --git a/worldeditadditions_core/utils/parse/axes_parser.lua b/worldeditadditions_core/utils/parse/axes_parser.lua index 678a050..d966256 100644 --- a/worldeditadditions_core/utils/parse/axes_parser.lua +++ b/worldeditadditions_core/utils/parse/axes_parser.lua @@ -23,7 +23,7 @@ else end ---- Unified Axis Keywords banks +--- Unified Axis Syntax banks local keywords = { -- Compass keywords compass = { @@ -36,7 +36,9 @@ local keywords = { ["w"] = "-x", ["west"] = "-x", ["-w"] = "x", ["-west"] = "x", ["u"] = "y", ["up"] = "y", + ["-u"] = "-y", ["-up"] = "-y", ["d"] = "-y", ["down"] = "-y", + ["-d"] = "y", ["-down"] = "y", }, -- Direction keywords @@ -90,9 +92,9 @@ function parse.num(str) else return false end end ---- Checks if a string is a valid Unified Axis Keyword. (Supports axis clumping) --- @param: str: String: Keyword instance to parse --- @returns: Key Instance: returns keyword type, processed keyword content and signed number (or nil) +--- Checks if a string is a valid Unified Axis Syntax. (Supports axis clumping) +-- @param: str: String: Keyword to parse +-- @returns: keyword type, processed keyword content and signed number (or nil) function parse.keyword(str) if type(str) ~= "string" then return "err", "Error: \""..tostring(str).."\" is not a string.", 404 @@ -135,68 +137,65 @@ end ---- Converts Unified Axis Keyword table into Vector3 instances. +--- Converts Unified Axis Syntax table into Vector3 instances. -- @param: tbl: Table: Keyword table to parse -- @param: facing: Table: Output from worldeditadditions_core.player_dir(name) -- @param: sum: Bool | String | nil: Return a single vector by summing the 2 output vectors together -- @returns: Vector3, [Vector3]: returns min, max Vector3 or sum Vector3 (if @param: sum ~= nil) -- if error: @returns: false, String: error message function parse.keytable(tbl, facing, sum) - local min, max = Vector3.new(), Vector3.new() - local expected = 1 - local tmp = {axes = {}, num = 0, sign = 1, mirror = false} + local min, max, mir= Vector3.new(), Vector3.new(), false + local neg, pos, v0 = Vector3.new(), Vector3.new(), Vector3.new() - --- Processes a number and adds it to the min and max vectors. - -- @param num The number to process. - -- @param axes The axes to apply the number to. - -- @param sign The sign of the number. - local function parseNumber(num, axes, sign) - if axes.rev then parseNumber(num, axes.rev, -sign) end - if num * sign >= 0 then - max = max:add(parse.vectorize(axes, num, sign)) + local function update(num) -- Update "min" and "max" + if num < 0 then + min, max = min:add(pos:mul(num)), max:add(neg:mul(num)) else - min = min:add(parse.vectorize(axes, num, sign)) + min, max = min:add(neg:mul(num)), max:add(pos:mul(num)) + end + neg, pos = v0:clone(), v0:clone() + end + + local function udir(axes, sign) -- Update "neg" and "pos" + if axes.rev then udir(axes.rev, -sign) end + for _, v in ipairs(axes) do + if sign < 0 then neg[v] = -1 + else pos[v] = 1 end end end - for i, v in ipairs(tbl) do + for i,v in ipairs(tbl) do if v:sub(1, 1) == "+" then v = v:sub(2) end - tmp.num = parse.num(v) + local num = parse.num(v) - if expected == 1 then - if tmp.num then - parseNumber(tmp.num, {"x", "y", "z", rev={"x", "y", "z"}}, tmp.sign) - else - local key_type, key_entry, key_sign = parse.keyword(v) + -- If we have a dimension add it to output + -- Else gather direction statements + if num then + -- Check for direction vectors + if neg == v0 and pos == v0 then + neg, pos = v0:add(-1), v0:add(1) + end + update(num) + else + local key_type, key_entry, key_sign = parse.keyword(v) if key_type == "axis" then - tmp.axes = key_entry - tmp.sign = key_sign + udir(key_entry, key_sign) elseif key_type == "dir" then - tmp.axes = {facing[key_entry].axis} - tmp.sign = facing[key_entry].sign * key_sign + udir({facing[key_entry].axis}, + facing[key_entry].sign * key_sign) elseif key_type == "rev" then - tmp.mirror = true + mir = true else return false, key_entry end - - expected = 2 - end - else - if tmp.num then - parseNumber(tmp.num, tmp.axes, tmp.sign) - expected = 1 - else - return false, "Error: Expected number after \""..tostring(tbl[i-1]).."\". Got \""..tostring(v).."\"." - end end end - if tmp.mirror and not sum then + if mir and not sum then max = max:max(min:abs()) min = max:multiply(-1) end @@ -209,6 +208,7 @@ function parse.keytable(tbl, facing, sum) end + return { keyword = parse.keyword, keytable = parse.keytable,