Scripting: Lua 5.4 with a fry library (shapes, own meshes, lathe, extrude, add/subtract/overlap, points, the look); a Script panel (F5 / Ctrl+Enter runs, one undo step, an error takes it all back), Script menu, example scripts, fry_run; tests run every example

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-10-20 17:07:51 +02:00
commit 62afbf2b1e
14 changed files with 1220 additions and 3 deletions

View file

@ -0,0 +1,16 @@
-- A box to print, with a lid and holes for M3 screws in its corners.
local w, d, h, wall = 0.08, 0.06, 0.04, 0.002
local box = fry.add("rounded_cube", {width = w, depth = d, height = h, name = "Box", color = "#d9d4c7"})
local inside = fry.add("cube", {width = w - 2 * wall, depth = d - 2 * wall, height = h})
inside.position = {0, 0, wall}
box:subtract(inside)
local lid = fry.add("cube", {width = w, depth = d, height = wall, name = "Lid", color = "#ff7828"})
lid.position = {w + 0.02, 0, 0}
for sx = -1, 1, 2 do
for sy = -1, 1, 2 do
local hole = fry.add("cylinder", {radius = 0.0016, height = 0.01, sides = 24})
hole.position = {w + 0.02 + sx * (w / 2 - 0.006), sy * (d / 2 - 0.006), -0.002}
lid:subtract(hole)
end
end
fry.frame()

View file

@ -0,0 +1,14 @@
-- A gear for 3D printing, with a hole for an M5 screw.
local teeth, radius, depth, thick = 16, 0.03, 0.004, 0.006 -- metres
local outline = {}
for i = 0, teeth * 4 - 1 do
local a = i / (teeth * 4) * 2 * math.pi
local r = (i % 4 < 2) and radius + depth or radius
outline[#outline + 1] = {math.cos(a) * r, math.sin(a) * r}
end
local gear = fry.extrude(outline, thick, "Gear")
gear.color = "#e0a030"
local hole = fry.add("cylinder", {radius = 0.0027, height = 0.02, sides = 32})
hole.position = {0, 0, -0.005}
gear:subtract(hole)
fry.frame()

View file

@ -0,0 +1,21 @@
-- A little town: random houses on a grid, each a folder of its own.
math.randomseed(7)
local roofs = {"#a8432f", "#5a6470", "#8c5a3c"}
for x = -2, 2 do
for y = -2, 2 do
local w, d, h = 0.6 + math.random() * 0.3, 0.6 + math.random() * 0.3, 0.5 + math.random() * 0.9
local walls = fry.add("cube", {width = w, depth = d, height = h, color = "#e8e0d0", name = "Walls"})
walls.position = {x * 1.4, y * 1.4, 0}
-- a wedge rises towards -X: two of them back to back make a ridge
local roof = fry.add("wedge", {width = d + 0.1, length = w / 2 + 0.05, height = 0.35, name = "Roof"})
local other = roof:copy()
roof.position = {x * 1.4 + w / 4 + 0.025, y * 1.4, h}
other.position = {x * 1.4 - w / 4 - 0.025, y * 1.4, h}
other.turn = {0, 0, 180}
local c = roofs[math.random(#roofs)]
roof.color, other.color = c, c
fry.group(string.format("House %d,%d", x, y), {walls, roof, other})
end
end
fry.look{sun_turn = 60, sun_height = 35}
fry.frame()

View file

@ -0,0 +1,15 @@
-- Spiral stairs round a pillar: change the numbers and run it again (F5).
local steps, rise, turn = 18, 0.18, 22 -- how many, how high each, degrees each
local width = 0.9
fry.add("pillar", {radius = 0.12, height = steps * rise + 0.3, color = "#8a8a90", name = "Post"})
local made = {}
for i = 0, steps - 1 do
local step = fry.add("cube", {width = width, depth = 0.32, height = 0.05, color = "#b07a4a", name = "Step"})
step.turn = {0, 0, i * turn}
local a = math.rad(i * turn)
step.position = {math.cos(a) * width / 2, math.sin(a) * width / 2, (i + 1) * rise}
made[#made + 1] = step
end
fry.group("Stairs", made)
fry.frame()

View file

@ -0,0 +1,15 @@
-- A vase turned on a lathe: the profile is {out, up} points from the bottom.
local profile = {}
local height, n = 0.4, 24
for i = 0, n do
local t = i / n
-- a belly low down, a neck, a lip
local r = 0.06 + 0.07 * math.sin(t * math.pi * 1.1) + 0.02 * t * t
profile[#profile + 1] = {r, t * height}
end
table.insert(profile, 1, {0, 0})
local vase = fry.lathe(profile, 64, "Vase")
vase.color = "#3c6e9f"
vase.rough = 0.25
vase:thicken(0.004) -- walls, so it prints hollow
fry.frame()

View file

@ -0,0 +1,12 @@
-- Points moved by a formula: a plane made into waves, then given a thickness.
local p = fry.add("plane", {width = 2, depth = 2, cuts = 40, name = "Waves"})
local pts = p:points()
for i, v in ipairs(pts) do
v.z = 0.08 * math.sin(v.x * 6) * math.cos(v.y * 5)
end
p:setpoints(pts)
p:thicken(0.03)
p.smooth = true
p.color = "#2f8f9d"
p:move(0, 0, 0.12)
fry.frame()