~fgaz/minetest-extruder

14bae4dc02619eef24493541ed1ac520a4821285 — Francesco Gazzetta 1 year, 3 months ago 919738f
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
          table.insert(to_visit, vector.add(pos, visit_direction))
        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)