diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 48997be..e8d80e3 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -32,6 +32,7 @@ dofile(wea.modpath.."/lib/spiral_circle.lua") dofile(wea.modpath.."/lib/dome.lua") dofile(wea.modpath.."/lib/spline.lua") dofile(wea.modpath.."/lib/revolve.lua") +dofile(wea.modpath.."/lib/rotate.lua") dofile(wea.modpath.."/lib/conv/conv.lua") dofile(wea.modpath.."/lib/erode/erode.lua") dofile(wea.modpath.."/lib/noise/init.lua") diff --git a/worldeditadditions_commands/commands/rotate.lua b/worldeditadditions_commands/commands/rotate.lua index 23b4653..8e40e79 100644 --- a/worldeditadditions_commands/commands/rotate.lua +++ b/worldeditadditions_commands/commands/rotate.lua @@ -8,7 +8,7 @@ local Vector3 = wea_c.Vector3 -- ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██████ ██ ██ ██ ██ ███████ -worldeditadditions_core.register_command("rotate", { +worldeditadditions_core.register_command("rotate+", { params = " [ ...] [origin|o []]", description = "Rotates the defined region arounnd the given axis by the given number of degrees. Angles are NOT limited to 90-degree increments. When multiple axes and angles are specified, these transformations are applied in order. If o [] is specified, then the specific position number (default: 3) is considered a custom rotation origin instead of the centre of the region. CAUTION: Rotating large areas of memory by 45° can be memory intensive!", privs = { worldedit = true }, @@ -17,6 +17,8 @@ worldeditadditions_core.register_command("rotate", { if not params_text then params_text = "" end local parts = wea_c.split_shell(params_text) + print("DEBUG:rotate/parse parts", wea_c.inspect(parts)) + local mode_store local mode = "AXIS" local success, axis_next, angle @@ -27,7 +29,14 @@ worldeditadditions_core.register_command("rotate", { for i,part in ipairs(parts) do if part == "origin" or part == "o" then mode_store = mode - mode = "ORIGIN" + + -- If the NEXT item is a number, then parse it. + if i < #parts and tonumber(parts[i+1]) ~= nil then + mode = "ORIGIN" + else + -- If not, then default to pos3 and continue in the original mode + origin = 3 + end elseif mode == "ORIGIN" then origin = tonumber(part) if not origin or origin < 1 then @@ -38,7 +47,7 @@ worldeditadditions_core.register_command("rotate", { mode = mode_store mode_store = nil elseif mode == "AXIS" then - axis_next = wea_c.parse.axis_rotation.axis_name(part) + success, axis_next = wea_c.parse.axes_rotation.axis_name(part) if not success then return success, axis_next end mode = "ANGLE" elseif mode == "ANGLE" then @@ -75,21 +84,32 @@ worldeditadditions_core.register_command("rotate", { end end + print("DEBUG:rotate/parse ORIGIN", origin, "rotlist", wea_c.inspect(rotlist)) + return true, origin, rotlist end, - nodes_needed = function(name, times) - -- TODO: .......this is a good question, actually. + nodes_needed = function(name, origin, rotlist) + -- BUG: .......this is a good question, actually. This naïve is flawed, since if we rotate by e.g. 45° we could end up replacing more nodes than if we rotate by 90° increments. This is further complicated by the allowance of a custom point of origin. + return Vector3.volume(wea_c.pos.get1(name), wea_c.pos.get2(name)) * 2 end, func = function(name, origin, rotlist) local start_time = wea_c.get_ms_time() - - -- TODO: Do rotation operation here. + ------------------------------------------------- + local pos_origin = wea_c.pos.get(name, origin) + local pos1, pos2 = wea_c.pos.get1(name), wea_c.pos.get2(name) + + local success, stats = worldeditadditions.rotate( + pos1, pos2, + pos_origin, + rotlist + ) + if not success then return success, stats end + ------------------------------------------------- local time_taken = wea_c.get_ms_time() - start_time - -- TODO: Update logging below. This will obviously crash due to unknown variables right now. - minetest.log("action", name .. " used //rotate at "..pos1.." - "..pos2.." with origin "..origin..", replacing "..changed.." nodes in "..time_taken.."s") - return true, changed.." nodes replaced in "..wea_c.format.human_time(time_taken) + minetest.log("action", name .. " used //rotate at "..pos1.." - "..pos2.." with origin "..pos_origin..", rotating "..stats.count_rotated.." nodes in "..time_taken.."s") + return true, stats.count_rotated.." nodes rotated through "..tostring(#rotlist).." rotations in "..wea_c.format.human_time(time_taken) end }) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index ac41f9f..5b00164 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -38,6 +38,7 @@ dofile(wea_cmd.modpath.."/commands/count.lua") dofile(wea_cmd.modpath.."/commands/sculpt.lua") dofile(wea_cmd.modpath.."/commands/spline.lua") dofile(wea_cmd.modpath.."/commands/revolve.lua") +dofile(wea_cmd.modpath.."/commands/rotate.lua") -- Meta Commands dofile(wea_cmd.modpath .. "/commands/meta/init.lua") diff --git a/worldeditadditions_core/core/run_command.lua b/worldeditadditions_core/core/run_command.lua index b0730af..78d6f2f 100644 --- a/worldeditadditions_core/core/run_command.lua +++ b/worldeditadditions_core/core/run_command.lua @@ -37,9 +37,6 @@ local function run_command(cmdname, options, player_name, paramtext) end local parse_result = { options.parse(paramtext) } - if #parse_result >= 2 and parse_result[1] == false and type(parse_result[2]) ~= "string" then - minetest.log("warning", "[WorldEditAdditions:core] This is a bug. Parsing function for cmd "..cmdname.." failed but provided value of type "..type(parse_result[2]).." as an error message instead of the expected value of type string.All output from the parsing function: "..wea_c.inspect(parse_result)) - end local success = table.remove(parse_result, 1) if not success then worldedit.player_notify(player_name, tostring(parse_result[1]) or "Invalid usage (no further error message was provided by the command. This is probably a bug.)") diff --git a/worldeditadditions_core/utils/parse/axes_rotation.lua b/worldeditadditions_core/utils/parse/axes_rotation.lua index ede628f..c675a91 100644 --- a/worldeditadditions_core/utils/parse/axes_rotation.lua +++ b/worldeditadditions_core/utils/parse/axes_rotation.lua @@ -21,7 +21,7 @@ function rot_axis_left(axis) elseif axis.z == 1 or axis.z == -1 then axis.x, axis.z = -axis.z, 0 end - return axis -- CAUDION, this function mutates! + return axis -- CAUTION, this function mutates! end --- Parses an axis name into a string. @@ -40,12 +40,12 @@ local function parse_rotation_axis_name(str, player) -- At most ONE of these cases is true at a time. -- Even if it were possible to handle more than one (which it isn't without quaternions which aren't used in the backend), we would have an undefined ordering problem with the application of such rotations. Rotations ≠ translations in this case! - if str:find("x", 1, true) then rotval.x = 1 - elseif str:find("y", 1, true) then rotval.y = 1 - elseif str:find("z", 1, true) then rotval.z = 1 - elseif str:find("left", 1, true) then rotval.z = -1 + if str:find("x", 1, true) then vector.x = 1 + elseif str:find("y", 1, true) then vector.y = 1 + elseif str:find("z", 1, true) then vector.z = 1 + elseif str:find("left", 1, true) then vector.z = -1 elseif str:find("right", 1, true) - or str:find("yaw") then rotval.z = 1 + or str:find("yaw") then vector.z = 1 elseif type(player) ~= "nil" then local player_rotation_h = calc_rotation_text(player:get_look_horizontal())