Pipe System
A 3dsMax-Tool written in MaxScript
April 3, 2017 - Tommy Dräger
Pipe System is a script that lets you append different elements on each other. The script was originally designed for schoolar purposes. The task was to build a modular system out of pipe-elements from a local industrial area. To achieve this every element got its own root and extension-point where the elements stacks on each other. You simply build your pipesystem by clicking the listed buttons or you can use your own custom meshes.
Download: (presets included)
Simply extract it inside the scripts folder of 3dsMax
Build arrangements with presets
Build arrangements with custom meshes
Hierarchically connected via dummies and points
PipeSystem GUI in 3dsMax
PipeSystemGUI.ms
rollout PipeSystem "PipeSystem v1.0"
(
groupBox rdo_grp "Preset Diameter" pos:[8,80] width:296 height:48
radioButtons rdo "" pos:[32,102] width:249 height:16
labels:#( "60cm",
"30cm",
"20cm")
default:1
columns:3
label footer "(c) FenixFox®Studios 2017"
pos:[8,376] width:296 height:24
GroupBox cstm_grp "Custom" pos:[8,8] width:296 height:64
pickButton ctm_btn "Pick Object" pos:[16,24] width:184 height:40
button ext_btn "Extend" pos:[208,24] width:88 height:40
groupBox ele_grp "Presets" pos:[8,136] width:296 height:160
button I_Pipe "I_Pipe" pos:[16,152] width:88 height:40
button I_Cap "I_Cap" pos:[112,152] width:88 height:40
button I_Isolation "I_Isolation" pos:[208,152] width:88 height:40
button L_Pipe_90_2 "L_Pipe_90_2" pos:[16,200] width:88 height:40
button L_Pipe_45_2 "L_Pipe_45_2" pos:[112,200] width:88 height:40
button L_Pipe_90_4 "L_Pipe_90_4" pos:[208,200] width:88 height:40
button L_Pipe_90_10 "L_Pipe_90_10" pos:[112,248] width:88 height:40
button L_Pipe_90_7 "L_Pipe_90_7" pos:[16,248] width:88 height:40
button T_V_Hopper "T_V_Hopper" pos:[208,248] width:88 height:40
GroupBox rot_grp "Rotate" pos:[8,304] width:296 height:64
button rot_left "Rotate -90" pos:[16,320] width:136 height:40
button rot_right "Rotate +90" pos:[160,320] width:136 height:40
function append_element picked_ele force_delete =
(
print force_delete
-- check whether the extensionobject got an own parent and child!
if picked_ele.parent == undefined OR
picked_ele.children[1] == undefined do
(
messagebox("Object needs a linked root <dummy> and extension <point>")
return()
)
-- if nothing is selected move the element to the origin
if $ == undefined do
(
extender = instance picked_ele
extender.wirecolor = (color 128 128 128)
extender.parent.pos = [0,0,0]
extender.pivot = extender.center
picked_ele.children[1].parent = extender
select extender
delete picked_ele
return()
)
-- check wether the selected object got a root and extensionpoint
if $.parent == undefined OR
$.children[1] == undefined do
(
messagebox("Selected object needs a linked root <dummy> and extension <point>")
return()
)
-- gets the object that needs to be extended
current_obj = $
-- creates a copy from the picked objekt
extender = instance picked_ele
extender.wirecolor = (color 128 128 128)
extender.pivot = extender.center
-- gets the parent and children node of the current selection
child = current_obj.children[1]
parent = current_obj.parent
-- create a new dummy and point
ext_child = Point pos:[0,0,0]
ext_child.rotation = picked_ele.children[1].rotation
ext_child.pos = picked_ele.children[1].pos
ext_child.wirecolor = (color 0 255 0)
-- throw error messagebox("text")
-- try catch block would be nice
-- to ensure the case of a missing child or parent
ext_parent = Dummy pos:[0,0,0]
ext_parent.rotation = picked_ele.parent.rotation
ext_parent.pos = picked_ele.parent.pos
ext_parent.wirecolor = (color 0 255 0)
-- the old children becomes the new parent
extender.parent = ext_parent
ext_child.parent = extender
-- move it to the destinated position
ext_parent.rotation = child.rotation
ext_parent.transform = child.transform
extender.name = uniquename(current_obj.name)
-- the new parent becomes the child of the child
ext_parent.parent = child
-- the created extended piece stays in focus
if force_delete == true do
(
delete picked_ele.parent
delete picked_ele.children[1]
delete picked_ele
)
select extender
)
function preset_load preset_name =
(
vert_array = #()
face_array = #()
sgroup_array = #()
matid_array = #()
edge_array = #()
in_name = ((GetDir #scripts)+"/PipeSystem/presets/" + preset_name + ".dat")
if in_name != undefined then
(
in_file = openFile in_name
if in_file != undefined then
(
dummy_transform = readValue in_file
point_transform = readValue in_file
num_verts = readValue in_file
num_faces = readValue in_file
for v = 1 to num_verts do
append vert_array (readValue in_file)
for f = 1 to num_faces do
(
append face_array (readValue in_file)
append sgroup_array (readValue in_file)
append matid_array (readValue in_file)
edge1 = readValue in_file
edge2 = readValue in_file
edge3 = readValue in_file
append edge_array #(edge1, edge2, edge3)
)
close in_file
new_mesh = mesh vertices:vert_array faces:face_array
for f = 1 to num_faces do
(
setFaceSmoothGroup new_mesh f sgroup_array[f]
setFaceMatID new_mesh f matid_array[f]
setEdgeVis new_mesh f 1 edge_array[f][1]
setEdgeVis new_mesh f 2 edge_array[f][2]
setEdgeVis new_mesh f 3 edge_array[f][3]
)
update new_mesh
parent = dummy pos:[0,0,0]
parent.wirecolor = (color 0 255 0)
parent.transform = dummy_transform
child = point pos:[0,0,0]
child.wirecolor = (color 0 255 0)
child.transform = point_transform
child.parent = new_mesh
new_mesh.parent = parent
return new_mesh
)
)
)
on I_Pipe pressed do
(
obj = preset_load("I_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on I_Isolation pressed do
(
obj = preset_load("I_Isolatoren_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on I_Cap pressed do
(
obj = preset_load("I_Caps_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on L_Pipe_90_2 pressed do
(
obj = preset_load("L_90_2_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on L_Pipe_45_2 pressed do
(
obj = preset_load("L_45_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on L_Pipe_90_4 pressed do
(
obj = preset_load("L_90_4_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on L_Pipe_90_10 pressed do
(
obj = preset_load("L_90_10_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on L_Pipe_90_7 pressed do
(
obj = preset_load("L_90_7_Rohre_" + (60/rdo.state) as string)
append_element obj true
)
on T_V_Hopper pressed do
(
obj = preset_load("T_V_Hopper_" + (60/rdo.state) as string)
append_element obj true
)
on rot_left pressed do
(
in coordsys local rotate $.parent (angleaxis -90 [0,1,0])
)
on rot_right pressed do
(
in coordsys local rotate $.parent (angleaxis 90 [0,1,0])
)
on ctm_btn picked obj do
(
fn shape_filt obj = isKindOf obj Geometry
if obj != undefined do
(
ctm_btn.text = obj.name
)
)
on ext_btn pressed do
(
if getnodebyname(ctm_btn.text) != undefined do
(
obj = getnodebyname(ctm_btn.text)
append_element obj false
)
)
-- dotnet hack to change the icon of the rollout
on PipeSystem open do
(
d = (windows.getChildHWND 0 PipeSystem.title)[1]
WM_SETICON = 0x0080
ICON_SMALL = 0
icon = dotnetobject "System.Drawing.Icon" (getdir #scripts +
"\PipeSystem\icon\favicon.ico")
windows.SendMessage d WM_SETICON ICON_SMALL icon.handle
)
)
--PipeRolloutFloater = newRolloutFloater "PipeSystem v1.0" 312 400
--addRollout PipeSystem PipeRolloutFloater
createdialog PipeSystem 312 400