We use cookies on this site to enhance your user experience

Solid Modeling Plugin

Solid Modeling Plugin

Aug 29 2019, 9:35 AM PST 2 min

The Plugin service supports solid modeling operations. The Union, Negate, and Separate functions are all exposed and allow the exact functionality of the built in Studio buttons, allowing you to create custom Solid Modeling plugins.

Function Description
Union (instances) Takes a table of Instances and returns the resulting
Negate (instances) Takes a table of Instances and returns a table of a negation of all of the input Instances.
Separate(instances) Takes a table of Instances and returns a table containing all the resulting separated Instances.


In this example we will create a plugin to get the intersection of a selection of parts. An intersection is defined as the space where all of the selected objects overlap. Note that there is a fair amount of error checking. Solid modeling operations can occasionally fail so it is important to catch these cases so users are not left with a messy workspace.

local toolbar = plugin:CreateToolbar("CSG intersect")
local button = toolbar:CreateButton(

local storage = {}

-- Returns the intersection between a and b. Will return false if any
-- Solid modeling function errors.
function intersect( a, b )
	local parent = a.Parent
	local aplus = a:Clone()
	aplus.Parent = parent
	table.insert(storage, aplus)
	local amin = a:Clone()
	amin.Parent = parent
	amin = plugin:Negate({amin})[1]
	table.insert(storage, amin)	
	local bplus = b:Clone()
	bplus.Parent = parent
	table.insert(storage, bplus)	
	local bmin = b:Clone()
	bmin.Parent = parent
	bmin = plugin:Negate({bmin})[1]
	table.insert(storage, bmin)	
	local diffab = plugin:Union({aplus, bmin})
	if not diffab then return false end	
	diffab = plugin:Negate({diffab})[1]
	table.insert(storage, diffab)	
	local diffba = plugin:Union({bplus, amin})
	if not diffba then return false end	
	diffba = plugin:Negate({diffba})[1]
	table.insert(storage, diffba)	
	local plusab = plugin:Union({a,b})
	if not plusab then return false end
	table.insert(storage, plusab)	
	return plugin:Union({plusab, diffab, diffba})

	local objects = game.Selection:Get()
	-- Create a table to hold a copy of the original objects. If any solid modeling function fails
	-- we want to use this table to restore the parts to their original state.
	local copy = {}
	for _, thing in pairs(objects) do
		local copy0 = thing:Clone()
		copy0.Parent = thing.Parent
		table.insert(copy, copy0)
		-- Also using this loop to start keeping a reference of all new solid modeling parts. If a
		-- function fails we will want to delete all of these parts to keep the workspace clean
		table.insert(storage, thing)
	-- Get the first object in the selection and then try to intersect that with every other object in
	-- the selection one at a time.
	local first = objects[1]
	for i = 2, #objects do
		-- If intersect function fails then clear all of the newly created objects to keep the workspace
		-- clean
		if not intersect( first, objects[i] ) then
			for _, thing in pairs(storage) do
				if thing then thing:Destroy() end
			storage = nil
			error("Error creating intersection of the selected parts.")
	-- If we got to this point then all of the intersection operations succeded. Set an undo waypoint so
	-- user can undo the operation.
	-- Since the operation succeeded then we do not need the original parts. Clear these out.
	for _, thing in pairs(copy) do
		if thing then thing:Destroy() end

See Also

Solid Modeling
Plugin Tutorial

  • plugin