"""导入自己的模型 — register a local 3D model as a studio project. tripocli import -i ./my_model.glb --wait -o my.glb The file goes straight to S3, then ``import_user_model`` turns it into a project, after which every post-process operator (remesh / rig / animate / segment / ...) works on it. Verified body: ``{format, model:{bucket,key}, name, transform_matrix, use_original_uv}``. The UI lets you rotate the mesh before importing — that is what ``transform_matrix`` carries; the CLI imports as-is with the identity matrix. Note the studio drops custom materials and deep node hierarchies on import. """ from . import _common NAME = "import" HELP = "导入自己的 3D 模型(glb/obj/fbx/stl)为项目,之后可继续后处理" IDENTITY = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] def add_arguments(parser): parser.add_argument("-i", "--input", required=True, help="本地模型文件 (glb/obj/fbx/stl)") parser.add_argument("--name", help="项目显示名(默认用文件名)") parser.add_argument("--matrix", help="16 个数的 4x4 变换矩阵(默认单位矩阵),逗号分隔") parser.add_argument("--no-original-uv", action="store_true", help="不保留原始 UV(默认保留)") _common.add_wait_options(parser, "导入完成后保存到该路径(可选)") def parse_matrix(text): if not text: return IDENTITY values = [float(part) for part in text.replace(" ", "").split(",")] if len(values) != 16: raise ValueError("--matrix 需要恰好 16 个数字(4x4,逗号分隔)") return values def run(ctx): args = ctx.args ctx.out.line(f"📤 上传模型: {args.input}") payload = ctx.client.upload_model(args.input) body = { **payload, "name": args.name or payload["name"], "transform_matrix": parse_matrix(args.matrix), "use_original_uv": not args.no_original_uv, } data = ctx.client.get_data("POST", "/v2/studio/operation/import_user_model", body=body) if isinstance(data, list): data = data[0] if data else {} return _common.finish_single(ctx, data or {}, output=args.output, wait=args.wait, label="导入")