## ~fgaz/minetest-extruder

14bae4dc02619eef24493541ed1ac520a4821285 — Francesco Gazzetta 1 year, 3 months ago
```Add diagonal (go through vertices) setting
```
```1 files changed, 58 insertions(+), 11 deletions(-)

M init.lua
```
`M init.lua => init.lua +58 -11`
```@@ 32,7 32,34 @@ local function get_perpendiculars(vec)
}
end

-local function visit_wrapped(visited, to_visit, direction, perpendiculars)
+-- Get the four diagonal (wrt axes) "manhattan-unit" vectors perpendicular to a given one (parallel to an axis)
+local function get_diagonals(vec)
+  if vec.x ~= 0 then
+    return {
+      vector.new(0,  1,  1),
+      vector.new(0,  1, -1),
+      vector.new(0, -1,  1),
+      vector.new(0, -1, -1),
+    }
+  end
+  if vec.y ~= 0 then
+    return {
+      vector.new( 1, 0,  1),
+      vector.new( 1, 0, -1),
+      vector.new(-1, 0,  1),
+      vector.new(-1, 0, -1),
+    }
+  end
+  -- if vec.z ~= 0 then
+  return {
+    vector.new( 1,  1, 0),
+    vector.new( 1, -1, 0),
+    vector.new(-1,  1, 0),
+    vector.new(-1, -1, 0),
+  }
+end
+
+local function visit_wrapped(visited, to_visit, direction, neighbors)
local pos = table.remove(to_visit)
while pos do
if visited[vector.to_string(pos)] == nil then

@@ 43,7 70,7 @@ local function visit_wrapped(visited, to_visit, direction, perpendiculars)
visited[vector.to_string(pos)] = false
else
visited[vector.to_string(pos)] = node
-        for _,visit_direction in pairs(perpendiculars) do
+        for _,visit_direction in pairs(neighbors) do
end
end

@@ 52,9 79,18 @@ local function visit_wrapped(visited, to_visit, direction, perpendiculars)
end
end

-local function visit(pos, direction)
+local function visit(pos, direction, meta)
+  local diagonal = meta:get_int("diagonal") == 1
+
+  local neighbors = get_perpendiculars(direction)
+  if diagonal then
+    for _,v in ipairs(get_diagonals(direction)) do
+      table.insert(neighbors, v)
+    end
+  end
+
local visited = {}
-  visit_wrapped(visited, {pos}, direction, get_perpendiculars(direction))
+  visit_wrapped(visited, {pos}, direction, neighbors)
return visited
end

@@ 97,7 133,7 @@ local function use(placer, pointed_thing, meta, remove)
if placer == nil or pointed_thing == nil or pointed_thing.type ~= "node" then return end
if not check_privs_with_msg(placer) then return end
local direction = vector.direction(pointed_thing.under, pointed_thing.above)
-  local surface = visit(pointed_thing.under, direction)
+  local surface = visit(pointed_thing.under, direction, meta)
-- TODO ask for confirmation if surface is too big (block limit field/checkbox in formspec?)
-- confirmation can be "click again" (store previous above and under)
extrude(surface, direction, meta, remove)

@@ 105,10 141,11 @@ end

local settings_formspec = [[
formspec_version[3]
-  size[4,3.5]
-  button_exit[0.5,2.4;3,0.8;confirm;Confirm]
-  field[0.5,0.6;3,0.8;amount;Extrusion amount;%d]
-  checkbox[0.5,1.9;overwrite;Allow overwriting;%s]
+  size[8,4.5]
+  button_exit[0.5,3.2;7,0.8;confirm;Confirm]
+  field[0.5,0.7;2,0.8;amount;Extrusion amount;%d]
+  checkbox[0.5,2;overwrite;Allow overwriting;%s]
+  checkbox[0.5,2.7;diagonal;Select through vertices (diagonally);%s]
]]

minetest.register_tool(modname .. ":extruder", {

@@ 127,16 164,17 @@ minetest.register_tool(modname .. ":extruder", {
use(placer, pointed_thing, itemstack:get_meta(), false)
end,

-  -- TODO add "go/select through vertices" checkbox
-- TODO add "only extrude/select nodes of the same type"
on_secondary_use = function(itemstack, placer, _)
local meta = itemstack:get_meta()
local amount = math.max(1, meta:get_int("amount"))
local overwrite = meta:get_int("overwrite") == 1
+    local diagonal = meta:get_int("diagonal") == 1
minetest.show_formspec(placer:get_player_name(), modname .. ":settings",
string.format(settings_formspec,
amount,
-        overwrite and "true" or "false"
+        overwrite and "true" or "false",
+        diagonal and "true" or "false"
)
)
end,

@@ 168,9 206,18 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
overwrite = meta:get_int("overwrite") == 1
end

+  local diagonal
+  if fields.diagonal then
+    diagonal = fields.diagonal == "true"
+    meta:set_int("diagonal", diagonal and 1 or 0)
+  else
+    diagonal = meta:get_int("diagonal") == 1
+  end
+
meta:set_string("count_meta", table.concat({
amount == 1 and "" or tostring(amount),
overwrite and "!" or "",
+    diagonal and "✳" or "",
}, ""))

inventory:set_stack("main", wield_index, itemstack)

```