parapoly-runtime 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,223 @@
1
+ > ⚠️ 注意:
2
+ > 不要直接调用 Text2CADFacade.ts 的实现或接口信息。所有对 Text2CADFacade 的使用应通过规范化的 API 或文档说明进行,避免直接依赖其源码细节。
3
+
4
+ ---
5
+ applyTo: "**/*.part3d,**/*.part3d.js,**/Part3dCodeExporter*,**/part3d/**"
6
+ description: "Part3D 编辑器与 .part3d/.part3d.js 导出规范。涵盖 Part3dCodeExporter 架构、特征导出模式、sketch 可见度、颜色格式等。"
7
+ ---
8
+ # Part3D & .part3d.js 导出指南
9
+
10
+ ## 文件概览
11
+
12
+ | 文件类型 | 说明 |
13
+ |---|---|
14
+ | `.part3d` | Part3D 编辑器的项目文件(JSON 格式,Sprite 序列化树) |
15
+ | `.part3d.js` | 从 `.part3d` 导出的可执行 JS 代码,可在 code3d 运行时独立运行 |
16
+
17
+ ## 源码位置
18
+
19
+ ```
20
+ packages/parapoly-runtime/src/io/Part3dCodeExporter.ts ← 核心导出类(类库)
21
+ packages/parapoly-editor/src/io/Part3dCodeExporter.ts ← 向后兼容 re-export
22
+ packages/parapoly-editor/src/editors/part3d/ ← Part3D 编辑器
23
+ packages/parapoly-runtime/src/part/feature_node/ ← 特征节点定义
24
+ packages/parapoly-runtime/src/part/feature_node/op/ ← 操作型特征的 run() 逻辑
25
+ ```
26
+
27
+ ## Part3dCodeExporter API
28
+
29
+ ```typescript
30
+ import { Part3dCodeExporter } from "parapoly-runtime";
31
+
32
+ // 导出 FeatureContainerNode 为 .part3d.js 代码
33
+ let code = Part3dCodeExporter.export(feature_container, default_color?);
34
+ // feature_container: FeatureContainerNode 实例
35
+ // default_color: 默认颜色(默认 "#ffffff"),当节点无颜色时使用
36
+ ```
37
+
38
+ ## 导出代码结构
39
+
40
+ ```javascript
41
+ let main = function() {
42
+ let block3d_doc = new PartBlock3dDocument();
43
+
44
+ // Helpers
45
+ let __id_to_name = {}; // feature_id → 运行时节点名映射
46
+ let __saved_shapes = {}; // Boolean 操作前保存的 shape 引用
47
+ let __record_name = function(feature_id) { ... };
48
+ let __select_feature = function(feature_id) { ... };
49
+
50
+ // Feature summary(注释段,人类可读预览)
51
+ // Feature count: N
52
+ // [0] FeatureNodeSetBox op=union ...
53
+
54
+ // Executable export(可执行段)
55
+ block3d_doc.box("union", 10, 5, 3, "#ff0000");
56
+ __record_name("abc12345-...");
57
+ // ...
58
+
59
+ return block3d_doc;
60
+ };
61
+ ```
62
+
63
+ ## 导出模式分类
64
+
65
+ ### 模式 A:基础体(直接 PartBlock3dDocument API)
66
+
67
+ 适用于:Box, Cylinder, Sphere, Cone, Torus, Prism, Ellipsoid, Wedge, Trapezoid, Step
68
+
69
+ ```javascript
70
+ block3d_doc.box(op, x, y, z, color);
71
+ block3d_doc.translate(px, py, pz); // TransformComponent
72
+ block3d_doc.rotate_by_quaternion(rx, ry, rz, rw);
73
+ __record_name(feature_id);
74
+ ```
75
+
76
+ ### 模式 B:IIFE + ParaPolyShapeMaker(操作型特征)
77
+
78
+ 适用于:Extrude, Revolve, Sweep, Helix, Fillet, Chamfer, Shell, Draft, Mirror, Boolean, Transform
79
+
80
+ ```javascript
81
+ (function() {
82
+ let target_name = __id_to_name[target_id];
83
+ if (!target_name) { console.warn("..."); return; }
84
+ let root = block3d_doc.get_root_node();
85
+ let node = root.getChildByName(target_name, true);
86
+ // ... 获取 shape / 调用 ParaPolyShapeMaker.xxx() ...
87
+ let result_node = block3d_doc.push_node(op, name, color, false);
88
+ result_node.set_topo_shape(result_shape);
89
+ block3d_doc.pop_node();
90
+ node.set_archived(true);
91
+ node.set_op_feature_node_id(feature_id);
92
+ __record_name(feature_id);
93
+ })();
94
+ ```
95
+
96
+ ## 关键经验与注意事项
97
+
98
+ ### 1. 颜色格式必须带 `#` 前缀
99
+
100
+ `get_color()` 返回的值可能不带 `#`(如 `"ffffff"`),导出时必须补全:
101
+
102
+ ```typescript
103
+ let color = node.get_color ? node.get_color() : default_color;
104
+ if (color && !color.startsWith("#")) color = "#" + color;
105
+ ```
106
+
107
+ ### 2. Sketch 可见度保持
108
+
109
+ Part3D 中 Sketch 有两种独立的隐藏机制,导出时必须都保留:
110
+
111
+ | 属性 | 含义 | 设置方式 |
112
+ |---|---|---|
113
+ | `get_archived()` | 被操作消费后系统隐藏 | `update_feature_node_archived()` 计算 |
114
+ | `get_op_feature_node_id()` | 关联的消费操作 ID | 操作 run() 时持久化设置 |
115
+ | `get_visible()` | 用户通过眼睛图标隐藏 | 用户手动切换 |
116
+
117
+ **导出逻辑**:
118
+ ```typescript
119
+ // 创建 sketch 后立即检查并保持可见度
120
+ let is_archived = node.get_archived ? node.get_archived() : false;
121
+ let op_id = node.get_op_feature_node_id ? node.get_op_feature_node_id() : null;
122
+ let is_visible = node.get_visible ? node.get_visible() : true;
123
+ if (is_archived || op_id) {
124
+ lines.push(`block3d_doc.selected_node.set_archived(true);`);
125
+ }
126
+ if (!is_visible) {
127
+ lines.push(`block3d_doc.selected_node.set_visible(false);`);
128
+ }
129
+ ```
130
+
131
+ **为什么要检查 `op_id`**:`get_archived()` 依赖编辑器的 `update_feature_node_archived()` 调用,可能不是最新状态。`get_op_feature_node_id()` 是持久化属性,更可靠。
132
+
133
+ **`end_sketch()` 后 `selected_node` 指向**:`PartBlock3dDocument.end_sketch()` 执行 `this.selected_node = node`(sketch 节点),所以 `block3d_doc.selected_node.set_archived(true)` 能正确定位。
134
+
135
+ **渲染过滤**:`SpriteToNativeNode` 和 `Text2CADFacade.build()` 遍历节点时均跳过 `topo_shape_component.get_archived() === true` 的节点。
136
+
137
+ ### 3. Sketch 复用与重发射
138
+
139
+ 同一 sketch 被多次引用时(如被两个 Extrude 使用),需要在第二次引用前重新发射:
140
+
141
+ ```typescript
142
+ let consumed_sketches: Set<string> = new Set();
143
+ // 在 Extrude/Revolve 处理时:
144
+ if (target_id && consumed_sketches.has(target_id) && sketch_nodes.has(target_id)) {
145
+ lines.push(...Part3dCodeExporter.export_sketch_lines(sketch_nodes.get(target_id)));
146
+ lines.push(`__record_name(${JSON.stringify(target_id)});`);
147
+ }
148
+ consumed_sketches.add(target_id);
149
+ ```
150
+
151
+ ### 4. 操作型特征的归档配对
152
+
153
+ Extrude/Revolve/Fillet 等操作在 IIFE 中必须:
154
+ 1. 先取消归档:`node.set_archived(false); node.set_op_feature_node_id(null);`
155
+ 2. 执行操作
156
+ 3. 重新归档:`node.set_archived(true); node.set_op_feature_node_id(feature_id);`
157
+
158
+ 如果 `keep_original === true`,跳过步骤 3。
159
+
160
+ ### 5. `__saved_shapes` 用于 Boolean 后的引用
161
+
162
+ Boolean 操作会删除原始节点,但后续 Mirror/Fillet 等可能需要引用被删除节点的 shape。Boolean 在删除前保存:
163
+
164
+ ```javascript
165
+ __saved_shapes[target_name] = { shape: topo_shape.clone(), color: color };
166
+ ```
167
+
168
+ 后续操作查找目标时先查节点,再查 `__saved_shapes`:
169
+ ```javascript
170
+ let topo_shape;
171
+ if (node && node.get_topo_shape) {
172
+ topo_shape = node.get_topo_shape();
173
+ } else if (__saved_shapes[target_name]) {
174
+ topo_shape = __saved_shapes[target_name].shape;
175
+ }
176
+ ```
177
+
178
+ ### 6. 变换顺序差异
179
+
180
+ 不同特征对 `transform_native_shape` 的调用顺序不同:
181
+
182
+ | 特征 | 顺序 |
183
+ |---|---|
184
+ | Extrude | 先 extrude_shape → 再 transform_native_shape |
185
+ | Helix | 先 helix_shape → 再 transform_native_shape |
186
+ | Revolve | 先 transform_native_shape(wires) → 再 revolve_shape |
187
+ | Sweep | 先 transform(profile+path) → 再 sweep_shape |
188
+
189
+ ### 7. STEP 导入体的 base64 编码
190
+
191
+ `FeatureNodeSetStep` 的 content 可能是字符串或 Uint8Array,导出时统一转为 base64:
192
+
193
+ ```typescript
194
+ private static step_payload_base64(content: any): string {
195
+ if (!content) return "";
196
+ if (content instanceof Uint8Array) {
197
+ return btoa(String.fromCharCode(...content));
198
+ }
199
+ if (typeof content === "string") {
200
+ return btoa(content);
201
+ }
202
+ return "";
203
+ }
204
+ ```
205
+
206
+ 运行时通过 `block3d_doc.import_step_shape_by_string(op, base64, true, color)` 还原。
207
+
208
+ ### 8. 错误日志格式
209
+
210
+ 所有 IIFE 中的 warn 日志统一格式:
211
+ ```
212
+ [part3d.js #序号 操作类型 特征ID前8位] 消息
213
+ ```
214
+ 例如:`[part3d.js #3 Extrude abc12345] target_name not found for sketch def67890`
215
+
216
+ ## 修改 Exporter 的流程
217
+
218
+ 1. 定位源码:`packages/parapoly-runtime/src/part/feature_node/op/FeatureNode*.ts` 的 `run()` 方法
219
+ 2. 找到 `ParaPolyShapeMaker.xxx()` 调用及参数来源
220
+ 3. 注意变换顺序(transform 在操作前/后)
221
+ 4. 更新 `Part3dCodeExporter.ts` 中对应 `class_name.indexOf(...)` 分支
222
+ 5. 保持 IIFE 模式和归档配对
223
+ 6. 运行 `get_errors` 验证无 TypeScript 错误
@@ -0,0 +1,251 @@
1
+ > ⚠️ 注意:
2
+ > 不要直接调用 Text2CADFacade.ts 的实现或接口信息。所有对 Text2CADFacade 的使用应通过规范化的 API 或文档说明进行,避免直接依赖其源码细节。
3
+
4
+ ---
5
+ applyTo: "**/*.sketch3d,**/*.sketch3d.js,**/SketchCodeExporter*,**/sketch3d/**,**/sketch_node/**"
6
+ description: "Sketch3D 草图编辑器与 .sketch3d/.sketch3d.js 导出规范。涵盖 SketchCodeExporter 架构、几何导出、约束导出、可见度处理等。"
7
+ ---
8
+ # Sketch3D & .sketch3d.js 导出指南
9
+
10
+ ## 文件概览
11
+
12
+ | 文件类型 | 说明 |
13
+ |---|---|
14
+ | `.sketch3d` | Sketch3D 编辑器的项目文件(JSON 格式,SkContainerNode 序列化) |
15
+ | `.sketch3d.js` / `.code3d.js` | 从 sketch 导出的可执行 JS 代码 |
16
+
17
+ ## 源码位置
18
+
19
+ ```
20
+ packages/parapoly-runtime/src/io/SketchCodeExporter.ts ← 核心导出类(类库)
21
+ packages/parapoly-editor/src/io/SketchCodeExporter.ts ← 向后兼容 re-export
22
+ packages/parapoly-editor/src/editors/sketch3d/ ← Sketch3D 编辑器
23
+ packages/parapoly-runtime/src/part/sketch_node/ ← 草图节点定义
24
+ ```
25
+
26
+ ## SketchCodeExporter API
27
+
28
+ ```typescript
29
+ import { SketchCodeExporter } from "parapoly-runtime";
30
+
31
+ // 导出 SkContainerNode 为 .code3d.js 代码
32
+ let code = SketchCodeExporter.export(sk_container_node);
33
+ ```
34
+
35
+ ## 导出代码结构
36
+
37
+ **重要**:每个 `.sketch3d.js` 文件只包含一个有效的 sketch(一对 `start_sketch`/`end_sketch`)。所有几何体和约束都属于这同一个 sketch 上下文。AI 阅读时应将文件内容视为单一草图的完整定义。
38
+
39
+ ```javascript
40
+ // This .sketch3d.js file contains exactly ONE sketch (start_sketch/end_sketch pair).
41
+ // All geometry and constraints belong to this single sketch context.
42
+ let main = function() {
43
+ let block3d_doc = new PartBlock3dDocument();
44
+ block3d_doc.start_sketch("sketch", [0, 0, 0, 0, 0, 1]);
45
+
46
+ // 几何绘制(返回 geom_id)
47
+ let g0 = block3d_doc.line_segment(0, 0, 0, 10, 0, 0);
48
+ let g1 = block3d_doc.line_segment(10, 0, 0, 10, 5, 0);
49
+ // ...
50
+
51
+ // 约束
52
+ block3d_doc.constraint_horizontal(g0);
53
+ block3d_doc.constraint_coincident(g0, PointPos.end, g1, PointPos.start);
54
+ // ...
55
+
56
+ block3d_doc.end_sketch();
57
+ return block3d_doc;
58
+ };
59
+ ```
60
+
61
+ ### start_sketch 平面方向
62
+
63
+ `start_sketch` 的第二个参数是平面定义,导出时从 `SkContainerNode.get_ax2()` 的 `Ax2Component` 读取 center 和 direction,输出为 6 元素数组 `[cx, cy, cz, dx, dy, dz]`:
64
+
65
+ | 平面 | 数组值 |
66
+ |---|---|
67
+ | XY 平面(Z 方向) | `[0, 0, 0, 0, 0, 1]` |
68
+ | XZ 平面(Y 方向) | `[0, 0, 0, 0, 1, 0]` |
69
+ | YZ 平面(X 方向) | `[0, 0, 0, 1, 0, 0]` |
70
+ | 偏移平面 | `[0, 0, 10, 0, 0, 1]`(Z=10 处的 XY 平面) |
71
+ | 任意方向 | `[cx, cy, cz, dx, dy, dz]` |
72
+
73
+ 也支持字符串简写形式(仅限手写代码):`"x"`, `"y"`, `"z"`。
74
+
75
+ ## 几何类型映射
76
+
77
+ | 节点类 | 导出方法 | 返回值 |
78
+ |---|---|---|
79
+ | `SkGeomPointNode` | `block3d_doc.point(x, y, z)` | geom_id |
80
+ | `SkGeomLineNode` | `block3d_doc.line_segment(x1, y1, z1, x2, y2, z2)` | geom_id |
81
+ | `SkGeomCircleNode` | `block3d_doc.circle(cx, cy, cz, r)` | geom_id |
82
+ | `SkGeomEllipseNode` | `block3d_doc.ellipse(cx, cy, cz, major_r, minor_r)` | geom_id |
83
+ | `SkGeomArcNode` | `block3d_doc.arc(cx, cy, cz, r, start_deg, end_deg)` | geom_id |
84
+ | `SkGeomBSplineNode` | `start_bspline(closed)` + `add_pole()` × N + `end_bspline()` | 无返回值 |
85
+
86
+ ## 约束类型映射
87
+
88
+ | ConstraintType | 导出方法 | 条件 |
89
+ |---|---|---|
90
+ | `Coincident` | `constraint_coincident(s, sp, f, fp)` | — |
91
+ | `Horizontal` | `constraint_horizontal(f)` | 单线段 |
92
+ | `Horizontal` | `constraint_horizontal_points(f, fp, s, sp)` | 两点(`second >= 0` 且 `firstPos != none`) |
93
+ | `Vertical` | `constraint_vertical(f)` | 单线段 |
94
+ | `Vertical` | `constraint_vertical_points(f, fp, s, sp)` | 两点 |
95
+ | `Distance` | `constraint_distance(f, value)` | 无 second |
96
+ | `Distance` | `constraint_distance_points(f, fp, s, sp, value)` | 两点 |
97
+ | `Distance` | `constraint_distance_point_to_line(f, fp, s, value)` | 点到线 |
98
+ | `DistanceX` | `constraint_distance_h(f, value)` / `_points(...)` | — |
99
+ | `DistanceY` | `constraint_distance_v(f, value)` / `_points(...)` | — |
100
+ | `Radius` | `constraint_radius(f, value)` | — |
101
+ | `Diameter` | `constraint_diameter(f, value)` | — |
102
+ | `Parallel` | `constraint_parallel(f, s)` | — |
103
+ | `Perpendicular` | `constraint_perpendicular(f, s)` | — |
104
+ | `Equal` | `constraint_equal(f, s)` | — |
105
+ | `Tangent` | `constraint_tangent(f, s)` | — |
106
+ | `Angle` | `constraint_angle(f, value)` | 单线段(与 X 轴夹角) |
107
+ | `Angle` | `constraint_angle_lines(f, s, value)` | 两线夹角 |
108
+ | `PointOnObject` | `constraint_point_on_object(f, fp, s)` | — |
109
+ | `Symmetric` | `constraint_symmetric(f, fp, line, s, sp)` | — |
110
+
111
+ ## 关键经验与注意事项
112
+
113
+ ### 1. 跳过内部几何体
114
+
115
+ Sketch 中存在内部辅助几何(如坐标轴),必须跳过:
116
+
117
+ ```typescript
118
+ if (node.get_is_internal && node.get_is_internal()) {
119
+ continue;
120
+ }
121
+ ```
122
+
123
+ ### 2. 跳过 InternalAlignment 约束
124
+
125
+ ```typescript
126
+ if (type === ConstraintType.InternalAlignment) {
127
+ continue;
128
+ }
129
+ ```
130
+
131
+ ### 3. Arc 角度转换
132
+
133
+ `SkGeomArcNode` 存储弧度制,导出时需转为角度制:
134
+
135
+ ```typescript
136
+ let sa = node.component.get_start_angle(); // 弧度
137
+ let ea = node.component.get_end_angle(); // 弧度
138
+ // 导出时转为度
139
+ block3d_doc.arc(cx, cy, cz, r, sa * 180 / Math.PI, ea * 180 / Math.PI);
140
+ ```
141
+
142
+ ### 4. BSpline 无 geom_id 返回
143
+
144
+ `start_bspline` / `end_bspline` 不返回 geom_id,因此 BSpline 不参与约束引用:
145
+
146
+ ```typescript
147
+ if (className === ClassNames.SkGeomBSplineNode) {
148
+ // ... export poles ...
149
+ geom_id_to_var.delete(geom_id); // 不记录变量映射
150
+ }
151
+ ```
152
+
153
+ ### 5. geom_id 变量命名
154
+
155
+ 每个几何体的 geom_id 映射为 `g{id}` 变量名,约束中引用这些变量:
156
+
157
+ ```javascript
158
+ let g0 = block3d_doc.line_segment(...);
159
+ let g1 = block3d_doc.line_segment(...);
160
+ block3d_doc.constraint_coincident(g0, PointPos.end, g1, PointPos.start);
161
+ ```
162
+
163
+ ### 6. PointPos 枚举值
164
+
165
+ ```
166
+ PointPos.none = 0 // 整条边/线(用于 constraint_horizontal 等)
167
+ PointPos.start = 1 // 起点
168
+ PointPos.end = 2 // 终点
169
+ PointPos.mid = 3 // 中点(圆心等)
170
+ ```
171
+
172
+ ### 7. Coincident 约束参数顺序
173
+
174
+ 注意 Coincident 的参数顺序是 `(second, secondPos, first, firstPos)`,与其他约束不同:
175
+
176
+ ```typescript
177
+ case ConstraintType.Coincident:
178
+ return `block3d_doc.constraint_coincident(${s}, ${sp}, ${f}, ${fp});`;
179
+ ```
180
+
181
+ ## 在 Part3dCodeExporter 中的 Sketch 导出
182
+
183
+ Part3dCodeExporter 中嵌入 sketch 时使用简化版(不含约束,不含 geom_id 变量):
184
+
185
+ ```javascript
186
+ block3d_doc.start_sketch("sketch_name", [cx, cy, cz, dx, dy, dz]);
187
+ block3d_doc.line_segment(x1, y1, z1, x2, y2, z2);
188
+ block3d_doc.circle(cx, cy, cz, r);
189
+ // ...
190
+ block3d_doc.end_sketch();
191
+ ```
192
+
193
+ **差异**:
194
+ - `start_sketch` 参数为 `[center_x, center_y, center_z, dir_x, dir_y, dir_z]` 数组(Part3d 模式),而非 `"z"` 字符串(独立 sketch 模式)
195
+ - 不导出约束(拉伸/旋转只需要 wires 形状)
196
+ - 不保留 geom_id 变量
197
+
198
+ ## Sketch 可见度(在 Part3D 上下文中)
199
+
200
+ 当 Sketch 存在于 Part3D 特征树中时,有两种隐藏机制:
201
+
202
+ 1. **`archived = true`**:被 Extrude/Revolve 等操作消费后,系统设置
203
+ 2. **`visible = false`**:用户通过眼睛图标手动隐藏
204
+
205
+ Part3dCodeExporter 在导出 sketch 后需检查并保持可见度状态:
206
+
207
+ ```typescript
208
+ if (is_archived || op_id) {
209
+ lines.push(`block3d_doc.selected_node.set_archived(true);`);
210
+ }
211
+ if (!is_visible) {
212
+ lines.push(`block3d_doc.selected_node.set_visible(false);`);
213
+ }
214
+ ```
215
+
216
+ `get_op_feature_node_id()` 是最可靠的"已被消费"指标(持久化属性),优先于 `get_archived()`(计算属性)。
217
+
218
+ ## SkContainerNode 关键 API
219
+
220
+ ```typescript
221
+ // 坐标系
222
+ sk_node.get_ax2() → { center, direction }
223
+ sk_node.set_ax2(center: Vector3, direction: Vector3)
224
+
225
+ // 几何体容器
226
+ sk_node.get_geoms() → Node (children = SkGeom*Node[])
227
+
228
+ // 约束容器
229
+ sk_node.get_constraints() → Node (children = ConstraintNode[])
230
+
231
+ // 生成 wire shape(供 Extrude/Revolve 使用)
232
+ sk_node.to_wires_shape() → TopoDS_Shape
233
+
234
+ // 可见度
235
+ sk_node.get_archived() → boolean
236
+ sk_node.set_archived(v)
237
+ sk_node.get_visible() → boolean
238
+ sk_node.set_visible(v)
239
+
240
+ // 操作关联
241
+ sk_node.get_op_feature_node_id() → string | null
242
+ sk_node.set_op_feature_node_id(id)
243
+ ```
244
+
245
+ ## 修改 SketchCodeExporter 的流程
246
+
247
+ 1. 确认几何类型:`packages/parapoly-runtime/src/part/sketch_node/SkGeom*.ts`
248
+ 2. 确认约束类型:`packages/parapoly-runtime/src/types/Constraint.ts` (`ConstraintType` 枚举)
249
+ 3. 确认 API:`packages/parapoly-runtime/src/part/PartBlock3dDocument.ts` 中的 sketch 方法
250
+ 4. 更新 `SketchCodeExporter.ts` 中对应分支
251
+ 5. 注意约束参数的 `second >= 0` 条件判断(区分单目/双目约束)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "parapoly-runtime",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "ParaPoly 3D CAD Runtime — CSG modeling, sketch, and project builder",
5
5
  "main": "./parapoly_runtime.js",
6
6
  "types": "./parapoly_runtime.d.ts",
@@ -1,5 +1,5 @@
1
1
  declare module "parapoly-runtime" {
2
- export type BooleanOp = "union" | "cut" | "common";
2
+ export type BooleanOp = "union" | "difference" | "intersection";
3
3
 
4
4
  export type AxisDir = "x" | "y" | "z";
5
5
 
@@ -33,6 +33,18 @@ declare module "parapoly-runtime" {
33
33
  private _parameters: Array<FacadeParameter>;
34
34
  private _lastBuildResult: FacadeBuildResult | null;
35
35
  constructor();
36
+ /**
37
+ * Reset the facade to a fresh empty document.
38
+ */
39
+ reset(): this;
40
+ /**
41
+ * Load a .part3d JSON payload into the facade document.
42
+ */
43
+ loadPart3d(json: string, recompile?: boolean, color?: string): this;
44
+ /**
45
+ * Load a .block3d JSON payload into the facade document.
46
+ */
47
+ loadBlock3d(json: string): this;
36
48
  /**
37
49
  * Create a box centered at origin. Parameters: x-size, y-size (height), z-size (depth).
38
50
  */
@@ -1735,7 +1747,7 @@ declare module "parapoly-runtime" {
1735
1747
  public getChildByIndex(index: number): Node;
1736
1748
  public clearComponents(): void;
1737
1749
  public clearChildren(): void;
1738
- public static visit_node(node: Node, preVisitMethod?: any, postVisitMethod?: any): void;
1750
+ public static visit_node(node: Node, preVisitMethod?: ((node: any) => void) | null, postVisitMethod?: ((node: any) => void) | null): void;
1739
1751
  public to_json(options?: ObjectToJsonOptions): any;
1740
1752
  public clone(options?: ObjectToJsonOptions, to_options?: ObjectToJsonOptions): Node;
1741
1753
  public static create(obj?: any, options?: ObjectCreateOptions): Node;
@@ -1777,6 +1789,12 @@ declare module "parapoly-runtime" {
1777
1789
  * @param color Optional override color
1778
1790
  */
1779
1791
  public static create_doc_from_part3d(json_str: string, recompile?: boolean, color?: string): PartBlock3dDocument;
1792
+ /**
1793
+ * Create a PartBlock3dDocument from a .block3d file's raw JSON string.
1794
+ * Extracts the stored JavaScript code from BlockCodeComponent and executes it.
1795
+ * @param json_str The raw JSON content of the .block3d file
1796
+ */
1797
+ public static create_doc_from_block3d(json_str: string): PartBlock3dDocument;
1780
1798
  public set_root_node(node: Node): void;
1781
1799
  public get_root_node(): Node;
1782
1800
  public to_json(): any;
@@ -1822,14 +1840,37 @@ declare module "parapoly-runtime" {
1822
1840
  public start_sketch(name: string, plane_dir: any): SkContainerNode;
1823
1841
  public end_sketch(): void;
1824
1842
  public get_sketch_ax2_component(): Ax2Component;
1825
- public point(x: number, y: number, z: number): void;
1826
- public line_segment(start_x: number, start_y: number, start_z: number, end_x: number, end_y: number, end_z: number): void;
1827
- public circle(x: number, y: number, z: number, r: number): void;
1828
- public ellipse(x: number, y: number, z: number, major_r: number, minor_r: number): void;
1829
- public arc(x: number, y: number, z: number, r: number, startAngle: number, endAngle: number, isDegree?: boolean): void;
1843
+ public point(x: number, y: number, z: number): number;
1844
+ public line_segment(start_x: number, start_y: number, start_z: number, end_x: number, end_y: number, end_z: number): number;
1845
+ public circle(x: number, y: number, z: number, r: number): number;
1846
+ public ellipse(x: number, y: number, z: number, major_r: number, minor_r: number): number;
1847
+ public arc(x: number, y: number, z: number, r: number, startAngle: number, endAngle: number, isDegree?: boolean): number;
1830
1848
  public start_bspline(closed: boolean): void;
1831
1849
  public end_bspline(): void;
1832
1850
  public add_pole(x: number, y: number, z: number): void;
1851
+ private get_sk_container(): SkContainerNode | null;
1852
+ public constraint_coincident(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos): void;
1853
+ public constraint_horizontal(geom_id: number): void;
1854
+ public constraint_vertical(geom_id: number): void;
1855
+ public constraint_horizontal_points(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos): void;
1856
+ public constraint_vertical_points(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos): void;
1857
+ public constraint_distance(geom_id: number, value: number): void;
1858
+ public constraint_distance_points(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos, value: number): void;
1859
+ public constraint_distance_h(geom_id: number, value: number): void;
1860
+ public constraint_distance_h_points(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos, value: number): void;
1861
+ public constraint_distance_v(geom_id: number, value: number): void;
1862
+ public constraint_distance_v_points(from_geom_id: number, from_pos: PointPos, to_geom_id: number, to_pos: PointPos, value: number): void;
1863
+ public constraint_distance_point_to_line(point_geom_id: number, point_pos: PointPos, line_geom_id: number, value: number): void;
1864
+ public constraint_radius(geom_id: number, value: number): void;
1865
+ public constraint_diameter(geom_id: number, value: number): void;
1866
+ public constraint_parallel(geom_id_1: number, geom_id_2: number): void;
1867
+ public constraint_perpendicular(geom_id_1: number, geom_id_2: number): void;
1868
+ public constraint_equal(geom_id_1: number, geom_id_2: number): void;
1869
+ public constraint_tangent(geom_id_1: number, geom_id_2: number): void;
1870
+ public constraint_angle(geom_id: number, value: number): void;
1871
+ public constraint_angle_lines(geom_id_1: number, geom_id_2: number, value: number): void;
1872
+ public constraint_point_on_object(point_geom_id: number, point_pos: PointPos, obj_geom_id: number): void;
1873
+ public constraint_symmetric(geom_id_1: number, pos_1: PointPos, line_geom_id: number, geom_id_2: number, pos_2: PointPos): void;
1833
1874
  public extrude(op: BooleanTypes, length: number, color: string, bSolid: boolean, transform_matrix_arr: Array<number>): void;
1834
1875
  public extrude_by_face(op: BooleanTypes, length: number, face_index: number, direction: DirectionTypes, color: string, bSolid: boolean, bAutoCheckDir: boolean): void;
1835
1876
  public revolve(op: BooleanTypes, angle: number, axis: DirectionTypes | Array<number>, color: string, bSolid: boolean, transform_matrix_arr: Array<number>): void;
@@ -2878,6 +2919,7 @@ declare module "parapoly-runtime" {
2878
2919
  FeatureSetEllipsoid = "FeatureSetEllipsoid",
2879
2920
  FeatureSetWedge = "FeatureSetWedge",
2880
2921
  FeatureSetTrapezoid = "FeatureSetTrapezoid",
2922
+ FeatureSetStep = "FeatureSetStep",
2881
2923
  FeatureBoolean = "FeatureBoolean",
2882
2924
  FeatureExtrude = "FeatureExtrude",
2883
2925
  FeatureChamfer = "FeatureChamfer",
@@ -2928,6 +2970,7 @@ declare module "parapoly-runtime" {
2928
2970
  exportDocData = "exportDocData",
2929
2971
  exportLog = "exportLog",
2930
2972
  exportBlocklyPngs = "exportBlocklyPngs",
2973
+ exportCode3dJs = "exportCode3dJs",
2931
2974
  export3mf = "export3mf",
2932
2975
  exportStep = "exportStep",
2933
2976
  exportIges = "exportIges",
@@ -2954,6 +2997,8 @@ declare module "parapoly-runtime" {
2954
2997
  viewSketchExtrudeScript = "viewSketchExtrudeScript",
2955
2998
  copySketchRevolveScript = "copySketchRevolveScript",
2956
2999
  viewSketchRevolveScript = "viewSketchRevolveScript",
3000
+ exportSketch3dJs = "exportSketch3dJs",
3001
+ exportPart3dJs = "exportPart3dJs",
2957
3002
  }
2958
3003
 
2959
3004
  export enum GeomTypes {
@@ -3258,7 +3303,7 @@ declare module "parapoly-runtime" {
3258
3303
  * @param onProgress - Progress callback
3259
3304
  * @returns Bundle output string and metadata
3260
3305
  */
3261
- export function buildCode3dProject(files: Record<string, string>, config: Code3dProjectConfig, onProgress?: BuildProgress): Promise<{
3306
+ export function buildCode3dProject(files: Record<string, string>, config: Code3dProjectConfig, onProgress?: BuildProgress, fileLoader?: FileLoader): Promise<{
3262
3307
  output: string;
3263
3308
  binOutput: Uint8Array | null;
3264
3309
  result: BuildResult;
@@ -3347,6 +3392,36 @@ declare module "parapoly-runtime" {
3347
3392
  errors?: Array<string>;
3348
3393
  }
3349
3394
 
3395
+ export class Part3dCodeExporter {
3396
+ public static export(feature_container: FeatureContainerNode, default_color?: string): string;
3397
+ private static export_feature_summary(feature_container: FeatureContainerNode): Array<string>;
3398
+ private static export_executable_calls(feature_container: FeatureContainerNode, default_color?: string): Array<string>;
3399
+ private static export_sketch_lines(node: any): Array<string>;
3400
+ private static append_transform_lines(lines: Array<string>, node: any): void;
3401
+ private static extract_edges_and_target(items: Array<any>): {
3402
+ target_id: string;
3403
+ edges: Array<number>;
3404
+ };
3405
+ private static extract_faces_and_target(items: Array<any>): {
3406
+ target_id: string;
3407
+ faces: Array<number>;
3408
+ };
3409
+ private static step_payload_base64(content: Uint8Array): string;
3410
+ private static n(v: any): string;
3411
+ private static summarize_feature_node(index: number, node: any): string;
3412
+ private static summarize_feature_component(component: any): string;
3413
+ private static push_if_defined(target: Array<string>, key: string, value: any): void;
3414
+ private static to_simple_value(value: any): string;
3415
+ }
3416
+
3417
+ export class SketchCodeExporter {
3418
+ public static export(sk_container_node: SkContainerNode): string;
3419
+ private static n(v: number): string;
3420
+ private static pp(pos: PointPos): string;
3421
+ private static gv(geom_id: number, map: Map<number, string>): string;
3422
+ private static exportConstraint(type: ConstraintType, first: number, firstPos: PointPos, second: number, secondPos: PointPos, value: number, map: Map<number, string>): string | null;
3423
+ }
3424
+
3350
3425
  export class EventDispatcher {
3351
3426
  private _listeners: Record<string, Array<Func>>;
3352
3427
  private _unique_maps: {};
@@ -4229,6 +4304,13 @@ declare module "parapoly-runtime" {
4229
4304
  getId(): string;
4230
4305
  }
4231
4306
 
4307
+ /**
4308
+ * Optional file loader callback for on-demand loading.
4309
+ * Called when a file is needed but not yet in the files map.
4310
+ * Should return the file content string, or null if not found.
4311
+ */
4312
+ export type FileLoader = (filePath: string) => Promise<string | null>;
4313
+
4232
4314
  export interface Vector3Like {
4233
4315
  readonly x: number;
4234
4316
  readonly y: number;