|
|
|
|
|
|
|
local minetest, vector, math_abs, math_sign
|
|
|
|
= minetest, vector, math.abs, math.sign
|
|
|
|
|
|
|
|
local rotate_box_by_facedir = nc_extended_rotating.rotate.rotate_box_by_facedir
|
|
|
|
|
|
|
|
-- Default selection boxes for a node that doesn't have one them explicitly.
|
|
|
|
local DEFAULT_SELECTION_BOX = { min = vector.new(-0.5, -0.5, -0.5),
|
|
|
|
max = vector.new( 0.5, 0.5, 0.5) }
|
|
|
|
|
|
|
|
local utility = {}
|
|
|
|
|
|
|
|
-- Gets the active `selection_box` for the specified `node` which
|
|
|
|
-- has a `paramtype2` of `facedir`, based on its `param2` value.
|
|
|
|
function utility.get_node_active_selection_box(node)
|
|
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
local box = def.selection_box and def.selection_box.fixed
|
|
|
|
-- No need to rotate the default selection box.
|
|
|
|
if not box then return DEFAULT_SELECTION_BOX end
|
|
|
|
-- If node definition specifies multiple selection boxes, just pick the first (for now).
|
|
|
|
if type(box[1]) == "table" then box = box[1] end
|
|
|
|
-- Transform the `{ x1, y1, z1, x2, y2, z2 }` box to a `{ min, max }` one.
|
|
|
|
box = { min = vector.new(box[1], box[2], box[3]),
|
|
|
|
max = vector.new(box[4], box[5], box[6]) }
|
|
|
|
-- Rotate the box to face `facedir`.
|
|
|
|
rotate_box_by_facedir(box, node.param2)
|
|
|
|
return box
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Calculates the rotation vector from where a player is looking at on this node.
|
|
|
|
-- * If looking near an edge, the vector points in the direction of that edge.
|
|
|
|
-- * If looking near a corner, the vector similarly points in that direction.
|
|
|
|
-- * Otherwise, vector simply points away from the face.
|
|
|
|
function utility.rotation_vector_from_lookat(node, pointed_thing, edge_distance)
|
|
|
|
local box = utility.get_node_active_selection_box(node)
|
|
|
|
local center = (box.min + box.max) / 2
|
|
|
|
|
|
|
|
-- Calculate bounds, single vector describing the size of the selection box.
|
|
|
|
local bounds = box.max - center -- This extends both into positive and negative.
|
|
|
|
-- Calculate intersection point relative to these bounds.
|
|
|
|
local point = pointed_thing.intersection_point - pointed_thing.under - center
|
|
|
|
|
|
|
|
return point:combine(bounds, function(p, b)
|
|
|
|
return b - math_abs(p) <= edge_distance and math_sign(p) or 0 end)
|
|
|
|
end
|
|
|
|
|
|
|
|
function utility.nodecore_filtered_lookup(eq_func)
|
|
|
|
local lookup = {}
|
|
|
|
for i = 0, 23 do
|
|
|
|
local facedir = nodecore.facedirs[i]
|
|
|
|
for j = 0, #lookup - 1 do
|
|
|
|
local other = nodecore.facedirs[lookup[j]]
|
|
|
|
if eq_func(facedir, other) then lookup[i] = j; break end
|
|
|
|
end
|
|
|
|
lookup[i] = lookup[i] or i
|
|
|
|
end
|
|
|
|
return lookup
|
|
|
|
end
|
|
|
|
|
|
|
|
return utility
|