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
pipes

Build arrangements with custom meshes
extend

Hierarchically connected via dummies and points
rotate

PipeSystem GUI in 3dsMax
GUI

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