1
0
mirror of https://github.com/Uberi/Minetest-WorldEdit.git synced 2025-10-16 07:35:27 +02:00

Support relative directions in transformations

closes #256
This commit is contained in:
sfan5
2025-09-24 18:08:21 +02:00
parent 0573cd8755
commit ebb0a95e08
3 changed files with 101 additions and 64 deletions

View File

@@ -270,7 +270,7 @@ height `<height>`, space between walls `<spacer>`, composed of `<node>`.
//spiral 5 2 1 glass //spiral 5 2 1 glass
//spiral 7 1 5 mesecons:wire_00000000_off //spiral 7 1 5 mesecons:wire_00000000_off
### `//copy x/y/z/? <amount>` ### `//copy x/y/z/?/up/down/left/right/front/back <amount>`
Copy the current WorldEdit region along the given axis by `<amount>` nodes. Copy the current WorldEdit region along the given axis by `<amount>` nodes.
@@ -279,7 +279,7 @@ Copy the current WorldEdit region along the given axis by `<amount>` nodes.
//copy z +4 //copy z +4
//copy ? 8 //copy ? 8
### `//move x/y/z/? <amount>` ### `//move x/y/z/?/up/down/left/right/front/back <amount>`
Move the current WorldEdit positions and region along the given axis by `<amount>` nodes. Move the current WorldEdit positions and region along the given axis by `<amount>` nodes.
@@ -288,7 +288,7 @@ Move the current WorldEdit positions and region along the given axis by `<amount
//move z +4 //move z +4
//move ? -1 //move ? -1
### `//stack x/y/z/? <count>` ### `//stack x/y/z/?/up/down/left/right/front/back <count>`
Stack the current WorldEdit region along the given axis `<count>` times. Stack the current WorldEdit region along the given axis `<count>` times.
@@ -322,14 +322,14 @@ Transpose the current WorldEdit positions and region along given axes.
//transpose y z //transpose y z
//transpose ? y //transpose ? y
### `//flip x/y/z/?` ### `//flip x/y/z/?/up/down/left/right/front/back`
Flip the current WorldEdit region along the given axis. Flip the current WorldEdit region along the given axis.
//flip x //flip x
//flip ? //flip ?
### `//rotate x/y/z/? <angle>` ### `//rotate x/y/z/?/up/down/left/right/front/back <angle>`
Rotate the current WorldEdit positions and region along the given axis by angle `<angle>` (90 degree increment). Rotate the current WorldEdit positions and region along the given axis by angle `<angle>` (90 degree increment).

View File

@@ -52,6 +52,35 @@ register_test("//fixedpos", make_parsing_test("fixedpos", {
"", "",
})) }))
register_test("//copy", make_parsing_test("copy", {
"x 10",
"right +1",
"? -4",
}, {
"eee 1",
"up 0",
"",
}))
register_test("//rotate", make_parsing_test("rotate", {
"z 90",
"left -180",
}, {
"x 0",
"back 77",
"",
}))
register_test("//flip", make_parsing_test("flip", {
"y",
"down",
"?",
}, {
"1",
"",
}))
register_test("//inset", make_parsing_test("inset", { register_test("//inset", make_parsing_test("inset", {
"h 1", "h 1",
"v 0", "v 0",
@@ -61,6 +90,7 @@ register_test("//inset", make_parsing_test("inset", {
"x 4", "x 4",
"xyz 5", "xyz 5",
"v foo", "v foo",
"",
})) }))
register_test("//shift", make_parsing_test("shift", { register_test("//shift", make_parsing_test("shift", {
@@ -73,6 +103,7 @@ register_test("//shift", make_parsing_test("shift", {
"-z 9", "-z 9",
"xx -5", "xx -5",
"?? 123", "?? 123",
"",
})) }))
register_test("//expand", make_parsing_test("expand", { register_test("//expand", make_parsing_test("expand", {
@@ -86,6 +117,7 @@ register_test("//expand", make_parsing_test("expand", {
"x -4", "x -4",
"? 4 -333", "? 4 -333",
"stupid 5 5", "stupid 5 5",
"",
})) }))
register_test("//cubeapply", make_parsing_test("cubeapply", { register_test("//cubeapply", make_parsing_test("cubeapply", {

View File

@@ -1,32 +1,38 @@
local S = minetest.get_translator("worldedit_commands") local S = minetest.get_translator("worldedit_commands")
local VALID_DIR = worldedit.valid_directions
local function check_region(name) local function check_region(name)
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name]) return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
end end
local function parse_copylike(param)
local found, _, direction, amount = param:find("^([^%s]+)%s+([+-]?%d+)$")
if found == nil or not VALID_DIR[direction] then
return false
end
if tonumber(amount) == 0 then
return false
end
return true, direction, tonumber(amount)
end
worldedit.register_command("copy", { worldedit.register_command("copy", {
params = "x/y/z/? <amount>", params = tostring(VALID_DIR) .. " <amount>",
description = S("Copy the current WorldEdit region along the given axis by <amount> nodes"), description = S("Copy the current WorldEdit region along the given axis by <amount> nodes"),
category = S("Transformations"), category = S("Transformations"),
privs = {worldedit=true}, privs = {worldedit=true},
require_pos = 2, require_pos = 2,
parse = function(param) parse = parse_copylike,
local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") nodes_needed = function(name, direction, amount)
if found == nil then
return false
end
return true, axis, tonumber(amount)
end,
nodes_needed = function(name, axis, amount)
return check_region(name) * 2 return check_region(name) * 2
end, end,
func = function(name, axis, amount) func = function(name, direction, amount)
if axis == "?" then local axis, sign = worldedit.player_direction(name, direction)
local sign if not axis or not sign then
axis, sign = worldedit.player_axis(name) return false, S("Invalid if looking straight up or down")
amount = amount * sign
end end
amount = amount * sign
local count = worldedit.copy(worldedit.pos1[name], worldedit.pos2[name], axis, amount) local count = worldedit.copy(worldedit.pos1[name], worldedit.pos2[name], axis, amount)
return true, S("@1 nodes copied", count) return true, S("@1 nodes copied", count)
@@ -34,27 +40,21 @@ worldedit.register_command("copy", {
}) })
worldedit.register_command("move", { worldedit.register_command("move", {
params = "x/y/z/? <amount>", params = tostring(VALID_DIR) .. " <amount>",
description = S("Move the current WorldEdit region along the given axis by <amount> nodes"), description = S("Move the current WorldEdit region along the given axis by <amount> nodes"),
category = S("Transformations"), category = S("Transformations"),
privs = {worldedit=true}, privs = {worldedit=true},
require_pos = 2, require_pos = 2,
parse = function(param) parse = parse_copylike,
local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") nodes_needed = function(name, direction, amount)
if found == nil then
return false
end
return true, axis, tonumber(amount)
end,
nodes_needed = function(name, axis, amount)
return check_region(name) * 2 return check_region(name) * 2
end, end,
func = function(name, axis, amount) func = function(name, direction, amount)
if axis == "?" then local axis, sign = worldedit.player_direction(name, direction)
local sign if not axis or not sign then
axis, sign = worldedit.player_axis(name) return false, S("Invalid if looking straight up or down")
amount = amount * sign
end end
amount = amount * sign
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
local count = worldedit.move(pos1, pos2, axis, amount) local count = worldedit.move(pos1, pos2, axis, amount)
@@ -67,27 +67,21 @@ worldedit.register_command("move", {
}) })
worldedit.register_command("stack", { worldedit.register_command("stack", {
params = "x/y/z/? <count>", params = tostring(VALID_DIR) .. " <count>",
description = S("Stack the current WorldEdit region along the given axis <count> times"), description = S("Stack the current WorldEdit region along the given axis <count> times"),
category = S("Transformations"), category = S("Transformations"),
privs = {worldedit=true}, privs = {worldedit=true},
require_pos = 2, require_pos = 2,
parse = function(param) parse = parse_copylike,
local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$") nodes_needed = function(name, direction, repetitions)
if found == nil then
return false
end
return true, axis, tonumber(repetitions)
end,
nodes_needed = function(name, axis, repetitions)
return check_region(name) * math.abs(repetitions) return check_region(name) * math.abs(repetitions)
end, end,
func = function(name, axis, repetitions) func = function(name, direction, repetitions)
if axis == "?" then local axis, sign = worldedit.player_direction(name, direction)
local sign if not axis or not sign then
axis, sign = worldedit.player_axis(name) return false, S("Invalid if looking straight up or down")
repetitions = repetitions * sign
end end
repetitions = repetitions * sign
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
local count = worldedit.volume(pos1, pos2) * math.abs(repetitions) local count = worldedit.volume(pos1, pos2) * math.abs(repetitions)
@@ -149,9 +143,10 @@ worldedit.register_command("stretch", {
end, end,
func = function(name, stretchx, stretchy, stretchz) func = function(name, stretchx, stretchy, stretchz)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
local count, pos1, pos2 = worldedit.stretch(pos1, pos2, stretchx, stretchy, stretchz) local count
count, pos1, pos2 = worldedit.stretch(pos1, pos2, stretchx, stretchy, stretchz)
--reset markers to scaled positions -- reset markers to scaled positions
worldedit.pos1[name] = pos1 worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2 worldedit.pos2[name] = pos2
worldedit.marker_update(name) worldedit.marker_update(name)
@@ -180,9 +175,10 @@ worldedit.register_command("transpose", {
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
if axis1 == "?" then axis1 = worldedit.player_axis(name) end if axis1 == "?" then axis1 = worldedit.player_axis(name) end
if axis2 == "?" then axis2 = worldedit.player_axis(name) end if axis2 == "?" then axis2 = worldedit.player_axis(name) end
local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) local count
count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
--reset markers to transposed positions -- reset markers to transposed positions
worldedit.pos1[name] = pos1 worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2 worldedit.pos2[name] = pos2
worldedit.marker_update(name) worldedit.marker_update(name)
@@ -192,49 +188,58 @@ worldedit.register_command("transpose", {
}) })
worldedit.register_command("flip", { worldedit.register_command("flip", {
params = "x/y/z/?", params = tostring(VALID_DIR),
description = S("Flip the current WorldEdit region along the given axis"), description = S("Flip the current WorldEdit region along the given axis"),
category = S("Transformations"), category = S("Transformations"),
privs = {worldedit=true}, privs = {worldedit=true},
require_pos = 2, require_pos = 2,
parse = function(param) parse = function(param)
if param ~= "x" and param ~= "y" and param ~= "z" and param ~= "?" then if not VALID_DIR[param] then
return false return false
end end
return true, param return true, param
end, end,
nodes_needed = check_region, nodes_needed = check_region,
func = function(name, param) func = function(name, param)
if param == "?" then param = worldedit.player_axis(name) end local axis = worldedit.player_direction(name, param)
local count = worldedit.flip(worldedit.pos1[name], worldedit.pos2[name], param) if axis == nil then
return false, S("Invalid if looking straight up or down")
end
local count = worldedit.flip(worldedit.pos1[name], worldedit.pos2[name], axis)
return true, S("@1 nodes flipped", count) return true, S("@1 nodes flipped", count)
end, end,
}) })
worldedit.register_command("rotate", { worldedit.register_command("rotate", {
params = "x/y/z/? <angle>", params = tostring(VALID_DIR) .. " <angle>",
description = S("Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)"), description = S("Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)"),
category = S("Transformations"), category = S("Transformations"),
privs = {worldedit=true}, privs = {worldedit=true},
require_pos = 2, require_pos = 2,
parse = function(param) parse = function(param)
local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") local found, _, direction, angle = param:find("^([^%s]+)%s+([+-]?%d+)$")
if found == nil then if found == nil or not VALID_DIR[direction] then
return false return false
end end
angle = tonumber(angle) angle = tonumber(angle)
if angle % 90 ~= 0 or angle % 360 == 0 then if angle % 90 ~= 0 or angle % 360 == 0 then
return false, S("invalid usage: angle must be multiple of 90") return false, S("invalid usage: angle must be multiple of 90")
end end
return true, axis, angle return true, direction, angle
end, end,
nodes_needed = check_region, nodes_needed = check_region,
func = function(name, axis, angle) func = function(name, direction, angle)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local axis = worldedit.player_direction(name, direction)
if axis == "?" then axis = worldedit.player_axis(name) end if axis == nil then
local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle) return false, S("Invalid if looking straight up or down")
end
--reset markers to rotated positions local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
local count
count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle)
-- reset markers to rotated positions
worldedit.pos1[name] = pos1 worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2 worldedit.pos2[name] = pos2
worldedit.marker_update(name) worldedit.marker_update(name)