diff --git a/worldeditadditions_commands/commands/selectors/sfactor.lua b/worldeditadditions_commands/commands/selectors/sfactor.lua new file mode 100644 index 0000000..aecd525 --- /dev/null +++ b/worldeditadditions_commands/commands/selectors/sfactor.lua @@ -0,0 +1,105 @@ +-- ███████ ███████ █████ ██████ ████████ ██████ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ █████ ███████ ██ ██ ██ ██ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ██ ██ ██████ ██ ██████ ██ ██ +local wea = worldeditadditions +worldedit.register_command("sfactor", { + params = " []", + description = "Make the length of one or more target axes of the current selection to be multiple(s) of .", + privs = { worldedit = true }, + require_pos = 2, + parse = function(params_text) + local parts = wea.split(params_text, "%s+", false) + + --- Dissable command for current release + if false then + return false, "Feature not yet implemented." + end + + if #parts < 2 then + return false, "Error: Not enough arguments. Expected \" []\"." + end + local mode, fac, targ = unpack(parts) + local modeSet = wea.makeset {"grow", "shrink", "avg"} + + -- Mode parsing + if mode == "average" then -- If mode is average set to avg + mode = "avg" + elseif not modeSet[mode] then -- If mode is invalid throw error + return false, "Error: Invalid \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"." + end + + -- Factor parsing + local factest = tonumber(fac) + if not factest then + return false, "Error: Invalid \""..fac.."\". Expected a number." + elseif factest < 2 then + return false, "Error: is too low. Expected a number equal to or greater than 2." + else + fac = math.floor(factest+0.5) + end + + -- Target parsing + if not targ then -- If no target set to default (xz) + targ = "xz" + elseif targ:match("[xyz]+") then -- ensure correct target syntax + targ = table.concat(wea.tochars(targ:match("[xyz]+"),true,true)) + else + return false, "Error: Invalid \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"." + end + + if false then -- Argument test + return false, ": " .. tostring(mode) .. ", : " .. type(fac) .. ", : " .. tostring(targ) + end + + return true, mode, fac, targ + end, + func = function(name, mode, fac, targ) + local p1, p2 = vector.new(worldedit.pos1[name]), vector.new(worldedit.pos2[name]) + local delta = vector.subtract(p2,p1) -- local delta equation: Vd(a) = V2(a) - V1(a) + local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg" + local targ = wea.tocharset(targ) -- Break up targ string into set table + local _m = 0 -- _m is the container to hold the average of the axes in targ + + -- set _m to the max, min or mean of the target axes depending on mode (_tl is the length of targ) or base if it exists + if mode == "avg" then + for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end + _m = _m / _tl + end + + -- Equasion: round(delta[] / factor) * factor + local eval = function(int,fac) + local tmp, abs, neg = int / fac, math.abs(int), int < 0 + + if mode == "avg" then + if int > _m then int = math.floor(abs / fac) * fac + else int = math.ceil(abs / fac) * fac end + elseif mode == "shrink" then int = math.floor(abs / fac) * fac + else int = math.ceil(abs / fac) * fac end + + if int < fac then int = fac end -- Ensure small selections aren't collapsed to 0 + if neg then int = int * -1 end -- Ensure correct facing direction + return int + end + + --- Test: + if false then + local brk = "" + for k,v in pairs(targ) do + brk = brk..k..": "..delta[k]..", " + delta[k] = eval(delta[k],fac) + brk = brk..k..": "..delta[k]..", " + end + return false, brk + end + -- //multi //fp set1 589 2 -82 //fp set2 615 2 -53 + -- //smake even shrink + + for k,v in pairs(targ) do delta[k] = eval(delta[k],fac) end + + worldedit.pos2[name] = vector.add(p1,delta) + worldedit.mark_pos2(name) + return true, "position 2 set to " .. minetest.pos_to_string(p2) + end +})