mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-01 19:23:00 +00:00
81 lines
2.8 KiB
Lua
81 lines
2.8 KiB
Lua
|
local wea_c = worldeditadditions_core
|
||
|
local Vector3 = wea_c.Vector3
|
||
|
|
||
|
-- ███████ ██████ ██ ██ ███ ██ ███████
|
||
|
-- ██ ██ ██ ██ ██ ████ ██ ██
|
||
|
-- ███████ ██████ ██ ██ ██ ██ ██ █████
|
||
|
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||
|
-- ███████ ██ ███████ ██ ██ ████ ███████
|
||
|
|
||
|
--- Creates a spline that follows the given list of points.
|
||
|
-- @param pos_list Vector3[] The list of points that define the path the spline should follow. Minimum: 2
|
||
|
-- @param width_start number The width of the spline at the start.
|
||
|
-- @param width_end number The width of the spline at the end. If nil, then width_start is used.
|
||
|
-- @param steps number The number of smoothing passes to apply to the list of points.
|
||
|
-- @param target_node Vector3 The *normalised* name of the node to use to build the square spiral with.
|
||
|
-- @returns bool,number|string A success boolean value, followed by either the number of the nodes set or an error message string.
|
||
|
function worldeditadditions.spline(pos_list, width_start, width_end, steps, target_node)
|
||
|
if #pos_list < 2 then return false, "Error: At least 2 positions are required to make a spline." end
|
||
|
if not width_end then width_end = width_start end
|
||
|
|
||
|
---
|
||
|
-- 0: Find bounding box
|
||
|
---
|
||
|
-- We can't use wea_c.pos.get_bounds 'cause that requires a player name
|
||
|
local pos1, pos2 = pos_list[1], pos_list[2]
|
||
|
for _, pos in pairs(pos_list) do
|
||
|
pos1, pos2 = Vector3.expand_region(pos, pos1, pos2)
|
||
|
end
|
||
|
local max_width = math.max(width_start, width_end)
|
||
|
pos1 = pos1 - max_width
|
||
|
pos2 = pos2 + max_width
|
||
|
|
||
|
|
||
|
---
|
||
|
-- 1: Interpolate points & widths
|
||
|
---
|
||
|
local pos_list_chaikin = wea_c.chaikin(pos_list, steps)
|
||
|
|
||
|
local widths_lerped = {}
|
||
|
for i = 1, #pos_list_chaikin do
|
||
|
table.insert(
|
||
|
widths_lerped,
|
||
|
wea_c.lerp(width_start, width_end, (1/#pos_list_chaikin)*(i-1))
|
||
|
)
|
||
|
end
|
||
|
|
||
|
---
|
||
|
-- 2: Fetch VoxelManipulator, prepare for replacement
|
||
|
---
|
||
|
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
|
||
|
local data = manip:get_data()
|
||
|
|
||
|
local node_id = minetest.get_content_id(target_node)
|
||
|
|
||
|
local count = 0 -- The number of nodes replaced
|
||
|
|
||
|
---
|
||
|
-- 3: Replace nodes
|
||
|
---
|
||
|
|
||
|
for i = 1, #pos_list_chaikin do
|
||
|
local pos_next = pos_list_chaikin[i]
|
||
|
local width_next = widths_lerped[i]
|
||
|
|
||
|
-- For now, just plot a point at each node
|
||
|
local index_node = area:index(pos_next.x, pos_next.y, pos_next.z)
|
||
|
data[index_node] = node_id
|
||
|
|
||
|
count = count + 1
|
||
|
end
|
||
|
|
||
|
---
|
||
|
-- 4: Save changes and return
|
||
|
---
|
||
|
|
||
|
-- Save the modified nodes back to disk & return
|
||
|
worldedit.manip_helpers.finish(manip, data)
|
||
|
|
||
|
return true, count
|
||
|
end
|