Custom Part varmain/aqa scripting in Plant 3D using python
14:57 11 Jun 2026

Im trying to make a T-Shoe part in Plant 3D one that can support pipes. I have two L brackets beside the Tshoe that are fine and the entire geometry works. However, when I go to update the properties in the shape after putting it through spec editor the whole shape gets destroyed when I update the length of S (change in distance from the T-shoe). I dont know what to do anymore, S isnt connected to any of the shape parameters for the L brackets so I dont understand why the Shape of the L brackets change, and moreover the T-shoe drops down to the bottom.

from aqa.math import *
from varmain.primitiv import *
from varmain.var_basic import *
from varmain.custom import *

# =============================================================================
# MCA - upside-down T-Shoe pipe support with two symmetric L-guides
# =============================================================================
#
# HOW THE PARAMETERS BEHAVE (each one isolated -- no cross-effects):
#   D    : reserved (pipe diameter) -- moves/scales NOTHING
#   L, W : flange plate footprint
#   H, T : total shoe height / steel thickness (stem height = H - T)
#   S    : ONLY slides the two L-guides horizontally. Guide centre = +/-(50+S),
#          so default S=25 lands at +/-75 (the confirmed-good position).
#   L-guide SIZE is fixed (hard-coded literals) -- properties cannot resize it.
#
# Every shape is placed directly at its FINAL display position: no rotateX
# flip, no fudge offsets. The shoe is anchored at BASE_Z (stem bottom), which
# never moves no matter what the parameters are -- so the part cannot "drop".
# Default values reproduce the previously confirmed render EXACTLY.

@activate(Group="Support", TooltipShort="Shoe support",
          TooltipLong="Upside-down T-Shoe with two symmetric side L-guides",
          LengthUnit="mm", Ports="1")
@group("MainDimensions")
@param(D = LENGTH, TooltipShort="Diameter of the pipe")
@param(L = LENGTH, TooltipShort="Length of the shoe")
@param(W = LENGTH, TooltipShort="Width of the flange")
@param(H = LENGTH, TooltipShort="Total height of the shoe")
@param(T = LENGTH, TooltipShort="Thickness of the steel")
@group("SideGuides")
@param(S = LENGTH0, TooltipShort="Gap from the flange edge to each L-guide")

def mca(s, D=80.0, L=150.0, W=100.0, H=100.0, T=12.0,
        S=25.0, ID="MCA", **kw):

    # Property edits can deliver values as strings -- coerce everything up
    # front so the arithmetic below can never break or half-build the part.
    D = float(D)
    L = float(L)
    W = float(W)
    H = float(H)
    T = float(T)
    S = float(S)

    # -------------------------------------------------------------------------
    # T-SHOE -- placed directly at final position, anchored at BASE_Z.
    # Defaults reproduce the confirmed render exactly:
    #   stem spans z -25..63, flange caps it spanning z 63..75
    # Changing H/T grows the shoe from the fixed base; nothing else moves it.
    # -------------------------------------------------------------------------
    BASE_Z = -25.0          # stem bottom: fixed anchor, parameter-independent
    stem_h = H - T

    body = BOX(s, L=L, W=W, H=T).translate(
        (0.0, 0.0, BASE_Z + stem_h + T / 2.0))   # flange caps the stem

    stem = BOX(s, L=L, W=T, H=stem_h).translate(
        (0.0, 0.0, BASE_Z + stem_h / 2.0))
    body.uniteWith(stem)
    stem.erase()

    # -------------------------------------------------------------------------
    # L-GUIDES -- size is FIXED literals (confirmed-good shape, do not
    # parametrise). S ONLY slides them along X: centre = +/-(50 + S).
    # With default S=25 the centres sit at +/-75, identical to before.
    # -------------------------------------------------------------------------
    guide_x = 50.0 + S

    # right guide
    foot_r = BOX(s, L=40.0, W=12.0, H=60.0).translate((0.0, 20.0, 6.0))
    web_r  = BOX(s, L=12.0, W=40.0, H=60.0).translate((0.0, -5.0, 20.0))
    foot_r.uniteWith(web_r)
    web_r.erase()
    foot_r.rotateZ(90.0)
    foot_r.translate((-guide_x, 0.0, 0.0))

    # left guide -- mirror of right, same internal literals
    foot_l = BOX(s, L=40.0, W=12.0, H=60.0).translate((0.0, -20.0, 6.0))
    web_l  = BOX(s, L=12.0, W=40.0, H=60.0).translate((0.0, 5.0, 20.0))
    foot_l.uniteWith(web_l)
    web_l.erase()
    foot_l.rotateZ(90.0)
    foot_l.translate((guide_x, 0.0, 0.0))

    # -------------------------------------------------------------------------
    # CONNECTION PORT  (unchanged)
    # -------------------------------------------------------------------------
    s.setPoint((0.0, 0.0, L + 30), (0.0, 1.0, 0.0))

python scripting