import csv import math from pathlib import Path # ----------------------- # CONFIG # ----------------------- CSV_PATH = "conveyors.csv" OUT_TSCN = "generated_conveyors.tscn" SCALE = 0.0254 # AutoCAD units → Godot units FIXED_Y = 2.5 BELT_RESOURCE_ID = "3_38ygf" # BeltConveyorAssembly.tscn # ----------------------- # HELPERS # ----------------------- def transform_from_points(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 length = math.hypot(dx, dy) * SCALE angle = math.atan2(dy, dx) mid_x = (x1 + x2) / 2 * SCALE mid_z = (y1 + y2) / 2 * SCALE # if you need flip: mid_z = -(y1 + y2)/2 * SCALE return { "length": length, "pos": (mid_x, FIXED_Y, mid_z), "rot_y": -angle } def transform3d(rot_y, x, y, z): c = math.cos(rot_y) s = math.sin(rot_y) return ( f"Transform3D({c}, 0, {s}, " f"0, 1, 0, " f"{-s}, 0, {c}, " f"{x}, {y}, {z})" ) # ----------------------- # READ CSV # ----------------------- conveyors = [] skipped = [] # (key, reason) def is_blank(v): return v is None or str(v).strip() == "" with open(CSV_PATH, newline="") as f: reader = csv.DictReader(f) for row in reader: key = (row.get("conveyor_key") or "").strip() included = (row.get("included") or "1").strip() if included == "0": skipped.append((key, "included=0 (no geometry)")) continue # guard against blank coords for col in ("start_x", "start_y", "end_x", "end_y"): if is_blank(row.get(col)): skipped.append((key, f"blank {col}")) break else: try: x1 = float(row["start_x"]) y1 = float(row["start_y"]) x2 = float(row["end_x"]) y2 = float(row["end_y"]) except ValueError as e: skipped.append((key, f"float parse error: {e}")) continue conv = transform_from_points(x1, y1, x2, y2) conv["name"] = key conveyors.append(conv) # optional: write a simple report so you can see what spurs are missing Path("skipped_conveyors.txt").write_text( "\n".join([f"{k}\t{r}" for k, r in skipped]), encoding="utf-8" ) # ----------------------- # WRITE TSCN # ----------------------- lines = [] lines.append('[gd_scene load_steps=2 format=3]') lines.append('') lines.append( '[ext_resource type="PackedScene" path="res://parts/assemblies/BeltConveyorAssembly.tscn" id="3_38ygf"]' ) lines.append('') lines.append('[node name="GeneratedConveyors" type="Node3D"]') lines.append('') for c in conveyors: x, y, z = c["pos"] t = transform3d(c["rot_y"], x, y, z) lines.append(f'[node name="{c["name"]}" parent="." instance=ExtResource("{BELT_RESOURCE_ID}")]') lines.append(f"transform = {t}") lines.append("right_side_guards_enabled = false") lines.append("left_side_guards_enabled = false") lines.append("head_end_leg_enabled = false") lines.append("tail_end_leg_enabled = false") lines.append("enable_comms = true") lines.append(f'speed_tag_name = "{c["name"]}_OIP"') lines.append(f"size = Vector3({c['length']:.6f}, 0.5, 1.524)") lines.append("") Path(OUT_TSCN).write_text("\n".join(lines), encoding="utf-8") print(f"Generated: {OUT_TSCN}") print(f"Skipped: {len(skipped)} (see skipped_conveyors.txt)")