-- Author: StrauntMaunt, Ola -- Name: Generate Fence on Spline -- Description: -- Icon:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAR5JREFUOI3NkrFKA0EQhr85civxPXwCS7GIRcD2sEprIcehWAlCStMLIXAKadNYpLOIhcc14hv4CoEEwSaR0x2LeGHvcsHYiH+zM//+O/Pv7MK/wlP/TH7SPN9GhdzLgzQONcuyT3czjUObxqF1uXdr1eVqeZBlHwAFB5twAjC6Pi502RTN875XA5hMXvNiWrGuuKjEsNOyw07L/pYTgMfeiV3TuaBzoACN6GZxhfF4KhVCt2AZq9ygHeigHdgSZwftQCt0S275jHe7c+Z1KwBHD01rhBcSSBpvcLXQXKQHygimO7Oilf37QzUCRlR9UTGeqhHEF9UtUfFFIyP0fE9PjWjXiOILs8u9ZDv/ieWhudNSoPeddh19fd2Zv8UX1Lt5pCkorycAAAAASUVORK5CYIIAFYxSCQAHAIB4ATog+X8AAGCKVovWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQh1eL1gEAAN7AzQEAAAAAAF52hNYBAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYIpWi9YBAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjEsJAAgAkOD8HP33fwAAkNivhdYBAAB8AAAAAAAAAI8PAAABAAAAkEZvhtYBAACw2K+F1gEAAMDYr4XWAQAAwNivhdYBAAAJBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDmKYbWAQAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/6gV+v+bgILT8Bf49AAAAAEoFDrT+/38/5uAgNAAAAAD6Bf69SgUONOoFfr8AAAAAAACwQQAAAAAAAIBBAACAPwAAAAAAAAAAAAAAAAAAAADQ3q+F1gEAAAAAAAAAAAAAAABIQwAAAAD/AP8AAABIQw== -- Hide: no -- AlwaysLoaded: no -- Version 25.06.01 -- Max amount of panels/poles places local amount = 200 -- Update the yOffset for the vertex offset shader with the angle -- 0 or nil to disable local offsetMultiplier = 2 -- Helper to lowercase safely local function lower(str) return string.lower(str or "") end -- Helper to get all children of a node local function getAllChildren(parent) local children = {} local numChildren = getNumOfChildren(parent) for i = 0, numChildren - 1 do local child = getChildAt(parent, i) table.insert(children, child) end return children end -- Random helper local function randomFromTable(t) return t[math.random(1, #t)] end -- Make sure at least 3 objects selected if getNumSelected() < 3 then print("Select at least 1 spline, 1 panel group or object, and 1 pole group or object") return end -- Sort selections into spline, panels, and poles local spline = nil local panels = {} local poles = {} for i = 0, getNumSelected() - 1 do local node = getSelection(i) local nodeName = lower(getName(node)) local numChildren = getNumOfChildren(node) if spline == nil then spline = node print("Detected spline: " .. getName(node)) else if nodeName:find("panel") then if numChildren > 0 then local panelChildren = getAllChildren(node) for _, child in ipairs(panelChildren) do table.insert(panels, child) print("Detected panel child: " .. getName(child)) end else table.insert(panels, node) print("Detected panel: " .. getName(node)) end elseif nodeName:find("pole") then if numChildren > 0 then local poleChildren = getAllChildren(node) for _, child in ipairs(poleChildren) do table.insert(poles, child) print("Detected pole child: " .. getName(child)) end else table.insert(poles, node) print("Detected pole: " .. getName(node)) end end end end if spline == nil or #panels == 0 or #poles == 0 then print("Error: Could not detect spline, panel(s), or pole(s). Make sure names contain 'panel' and 'pole'.") return end -- 🆕 Fence Length Detection from spline name local fenceLength = 2 -- default fallback local splineName = lower(getName(spline)) local foundLength = string.match(splineName, "_([%d%.]+)m") if foundLength then fenceLength = tonumber(foundLength) print("Fence length override detected from name: " .. fenceLength) else print("No fence length override found, using default: " .. fenceLength) end math.randomseed(getTime()) -- safe random seed for Giants Editor function connectPoints(template, startX, startY, startZ, endX, endY, endZ) local splinePoints = {endX, endY, endZ, startX, endY, startZ} local newSpline = createSplineFromEditPoints(getRootNode(), splinePoints, true, false) local rX, rY, rZ = getSplineOrientation(newSpline, 0, 0, -1, 0) delete(newSpline) local newFence = clone(template, false) link(getRootNode(), newFence) setWorldRotation(newFence, rX, rY, rZ) setWorldTranslation(newFence, startX, startY, startZ) return newFence end local spawnedObject = {} local mSplineLength = getSplineLength(spline) print("Spline length: " .. mSplineLength) local fenceLengthTime = 1 / (mSplineLength / fenceLength) print("Fence length time: " .. fenceLengthTime) local splinePos = 0.0 local lastEndX, lastEndY, lastEndZ = nil, nil, nil -- will store the last segment's end position -- Spawn all Objects for i = 0, amount do if splinePos <= 1.0 and ((splinePos + fenceLengthTime) <= 1.0) then local x, y, z = getSplinePosition(spline, splinePos) local endX, endY, endZ = getSplinePosition(spline, (splinePos + fenceLengthTime)) -- Randomly pick panel and pole local panel = randomFromTable(panels) local pole = randomFromTable(poles) local newPanel = connectPoints(panel, x, y, z, endX, endY, endZ) if (offsetMultiplier ~= nil and offsetMultiplier ~= 0) then local heightDifference = (endY - y) * offsetMultiplier local shaderParameterName = "yOffset" local xOffset, yOffset, zOffset, wOffset = 0, 0, 0, 0 xOffset = math.atan(heightDifference / fenceLength) setShaderParameterRecursive(newPanel, shaderParameterName, xOffset, yOffset, zOffset, wOffset, false) end table.insert(spawnedObject, newPanel) local newPole = connectPoints(pole, x, y, z, endX, endY, endZ) table.insert(spawnedObject, newPole) -- store the last end point lastEndX, lastEndY, lastEndZ = endX, endY, endZ splinePos = splinePos + fenceLengthTime else break end end -- Add a final pole at the END of the last panel segment if lastEndX ~= nil and lastEndY ~= nil and lastEndZ ~= nil then local finalPoleTemplate = randomFromTable(poles) local finalPole = clone(finalPoleTemplate, false) link(getRootNode(), finalPole) setWorldTranslation(finalPole, lastEndX, lastEndY, lastEndZ) table.insert(spawnedObject, finalPole) end -- Move Objects to parent Group local parentGroup = createTransformGroup("fence") link(getRootNode(), parentGroup) setWorldTranslation(parentGroup, getSplinePosition(spline, 0)) for i = 1, #spawnedObject do local x, y, z = getWorldTranslation(spawnedObject[i]) link(parentGroup, spawnedObject[i]) setWorldTranslation(spawnedObject[i], x, y, z) end print("Fence generated successfully with " .. tostring(#panels) .. " panel types and " .. tostring(#poles) .. " pole types.")