# Lena tank/tee -- WORKING recipe (verified on Lena's avatar 2026-07-30, # result: tools/tailor/lena_tee_v1.zprj + lena_tee_v1_garment.fbx). # Run inside a bridge session: # python tools/md_bridge.py --file tools/tailor/md_tee_v1.py --timeout 500 # # Prereq: Lena avatar imported at true scale. If GetAvatarCount() == 0: # op = ApiTypes.ImportExportOption(); op.scale = 10.0 # op.bAddArrangementPoints = True; op.bAutoTranslate = True # import_api.ImportFBX(r"...\tools\tailor\avatar\Lena_QuatSkin_Avatar.fbx", op) # (ImportAvatar() is for .avt files only -- returns False on FBX.) # # HARD-WON FACTS (do not rediscover): # - 2D pattern space: units are mm, +y is UP in the 3D mapping. Straps/neck # at HIGH y, hem at y=0. (Panels built y-down drape upside-down and tangle # at the neck -- looked like seam bugs, wasn't.) # - MD internal 3D unit is mm (gravity default -9800). Blender-exported FBX # avatars land 10x small -- import with op.scale = 10. # - CreatePatternWithPoints takes (x, y, type) triples; type 0 = corner. # Returned id is the pattern index; line i = edge point[i] -> point[i+1]. # - Seams: AddSeamlinePairGroup(patA, lineA, patB, lineB, False, False), # SAME line index both panels for front/back pairs (cross-pairing sews the # garment over the face). Whole-edge sewing only -> build the neck gap and # armholes into the outline as extra points. # - Placement: SetArrangement(pattern, arrangementIndex) assigns, then # utility_api.ResetClothArrangement() APPLIES it (ReDrape3DArrangement only # materializes not-yet-draped cloth). Arrangement indices REGENERATE when # the avatar changes -- always look up by name. # - utility_api.Simulate(nFrames) is synchronous; ~1 min per 300 frames. import os import tempfile REPO = r"C:\Users\Jeremy\tinqs\animation" report = {} n = pattern_api.GetPatternCount() for i in range(n - 1, -1, -1): pattern_api.DeletePatternPiece(i) # Measurements: chest 1083 mm + ease -> 590 panel; shoulder line 440 wide # (tips at x 75/515); neck gap 260 (x 165..425); front scoop 140 deep, back # straight; armhole 165 tall (y 455 down to 290); hem->strap 480. TOP = 480.0 def panel(scoop, dx, straight_back): if straight_back: neck = [(215.0, 455.0), (295.0, 455.0), (375.0, 455.0)] ny = 455.0 else: neck = [(215.0, TOP - scoop * 0.75), (295.0, TOP - scoop), (375.0, TOP - scoop * 0.75)] ny = TOP pts = ([(75.0, 455.0), (165.0, ny)] + neck + [(425.0, ny), (515.0, 455.0), (590.0, 290.0), (590.0, 0.0), (0.0, 0.0), (0.0, 290.0)]) return pattern_api.CreatePatternWithPoints([(x + dx, y, 0) for (x, y) in pts]) front = panel(140.0, 0.0, False) back = panel(0.0, 800.0, True) report["ids"] = [front, back] # Lines: 0 shoulder_L | 1-4 neckline (open) | 5 shoulder_R | 6 armhole_R # 7 side_R | 8 hem | 9 side_L | 10 armhole_L for line in (0, 5, 7, 9): pattern_api.AddSeamlinePairGroup(front, line, back, line, False, False) arr = {a["ArrangementName"]: int(a["ArrangementIndex"]) for a in pattern_api.GetArrangementList()} pattern_api.SetArrangement(front, arr["Body_Front_Center_1"]) pattern_api.SetArrangement(back, arr["Body_Back_Center_1"]) pattern_api.SetArrangementPosition(front, 50, 55, 50) pattern_api.SetArrangementPosition(back, 0, 55, 50) utility_api.ResetClothArrangement() report["sim"] = utility_api.Simulate(300) utility_api.Refresh3DWindow() snap = os.path.join(tempfile.gettempdir(), "tinqs_md_tee_final.png") export_api.ExportSnapshot3D(snap) report["snap"] = snap result = report