Engine 系统
大约 13 分钟
Engine 系统
Engine 是 WebCAD 的核心静态类,作为整个系统的全局入口点,提供对文档、画布、撤销管理、坐标变换等核心功能的访问。
概述
系统变量
颜色和样式变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CECOLOR | number | 256 | 当前实体颜色(256=随层,0=随块) |
CEALPHA | number | 1 | 当前实体透明度(0-1) |
CELTYPE | string | "ByLayer" | 当前实体线型 |
CELTSCALE | number | 1 | 当前实体线型比例 |
import { Engine } from 'vjcad';
// 颜色索引说明:
// 1=红色, 2=黄色, 3=绿色, 4=青色, 5=蓝色, 6=洋红, 7=白色
// 256=随层(ByLayer), 0=随块(ByBlock)
// 设置当前绘图颜色为红色
Engine.CECOLOR = 1;
// 设置线型为虚线
Engine.CELTYPE = "HIDDEN";
// 设置线型比例
Engine.CELTSCALE = 2.0;捕捉和绘图模式变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
OSMODE | number | 255 | 对象捕捉模式(位掩码) |
ORTHOMODE | number | 0 | 正交模式(0=关,1=开) |
POLARMODE | number | 0 | 极坐标模式(0=关,1=开) |
POLARANG | number | π/12 | 极坐标角度增量 |
GRIDMODE | number | 0 | 网格显示模式 |
对象捕捉模式位掩码
// OSMODE 位掩码定义
const OSNAP = {
ENDPOINT: 1, // 端点
MIDPOINT: 2, // 中点
CENTER: 4, // 圆心
NODE: 8, // 节点
QUADRANT: 16, // 象限点
INTERSECTION: 32, // 交点
INSERT: 64, // 插入点
PERPENDICULAR: 128, // 垂足
TANGENT: 256, // 切点
NEAREST: 512, // 最近点
APPARENT: 1024, // 外观交点
EXTENSION: 2048, // 延伸
PARALLEL: 4096, // 平行
};
// 启用所有捕捉
Engine.OSMODE = 255;
// 只启用端点和中点捕捉
Engine.OSMODE = OSNAP.ENDPOINT | OSNAP.MIDPOINT;
// 关闭所有捕捉
Engine.OSMODE = 0;
// 检查是否启用端点捕捉
const hasEndpoint = (Engine.OSMODE & OSNAP.ENDPOINT) !== 0;正交和极坐标模式
// 开启正交模式(限制光标移动为水平或垂直方向)
Engine.ORTHOMODE = 1;
// 开启极坐标模式
Engine.POLARMODE = 1;
// 设置极坐标角度增量(15度)
Engine.POLARANG = Math.PI / 12;
// 注意:正交模式和极坐标模式互斥,开启一个会自动关闭另一个显示和界面变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
APERTURE | number | 5 | 捕捉光圈大小(像素) |
PICKBOX | number | 5 | 选择框大小(像素) |
GRIPSIZE | number | 4 | 夹点大小(像素) |
CURSORSIZE | number | 64 | 十字光标大小(0=全屏) |
ZOOMFACTOR | number | 75 | 缩放因子 |
// 调整捕捉光圈大小
Engine.APERTURE = 10;
// 调整选择框大小
Engine.PICKBOX = 8;
// 设置十字光标为全屏
Engine.CURSORSIZE = 0;
// 设置缩放因子(影响滚轮缩放速度)
Engine.ZOOMFACTOR = 100;编辑相关变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
FILLETRAD | number | 0 | 圆角半径 |
OFFSETDIST | number | 10 | 偏移距离 |
PLINEWID | number | 0 | 多段线宽度 |
主题和高亮变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
THEME_MODE | number | 0 | 主题模式(0=深色,1=浅色) |
HLCOLOR | number | 172 | 高亮颜色索引 |
HLALPHA | number | 0.5 | 高亮透明度 |
// 切换到浅色主题
Engine.THEME_MODE = 1;
// 切换到深色主题
Engine.THEME_MODE = 0;
// 检查当前主题
if (Engine.isDarkTheme()) {
console.log('当前是深色主题');
}
// 获取当前主题背景色
const bgColor = Engine.getThemeBackground();核心组件访问
文档和空间
import { Engine, CadDocument, BlockDefinition } from 'vjcad';
// 获取当前文档
const doc: CadDocument = Engine.currentDoc;
console.log('文档名称:', doc.name);
console.log('文档路径:', doc.path);
// 获取当前空间(模型空间或布局空间)
const space: BlockDefinition = Engine.currentSpace;
console.log('当前空间中的实体数:', space.items.length);
// 访问图层集合
const layers = doc.layers;
console.log('图层数量:', layers.items.length);
// 访问块集合
const blocks = doc.blocks;画布控制器
import { Engine, CanvasController } from 'vjcad';
// 获取画布控制器(底层访问)
const canvas: CanvasController = Engine.pcanvas;
// 常用画布操作已封装到 Engine 静态方法,推荐直接使用:
Engine.zoomExtents(); // 全图显示
Engine.regen(); // 重新生成
Engine.redraw(); // 重绘
Engine.setCenter(point); // 设置视图中心
Engine.setBgc(0); // 设置背景色
Engine.resize(800, 600); // 调整大小
Engine.clearGrip(); // 清除夹点
Engine.clearOsnap(); // 清除捕捉标记
Engine.clearHighLight(); // 清除高亮
Engine.getScreenBoundsWcs(); // 获取屏幕范围
Engine.getScreenEntities(); // 获取屏幕内实体
// 获取视图缩放级别
const zoom = Engine.currentSpace.zoom;撤销管理器
import { Engine, UndoManager } from 'vjcad';
// 获取撤销管理器
const undoMgr: UndoManager = Engine.undoManager;
// 执行撤销
undoMgr.undo();
// 执行重做
undoMgr.redo();
// 检查是否可撤销
if (undoMgr.canUndo()) {
undoMgr.undo();
}坐标变换器
import { Engine, CoordinateTransform, Point2D } from 'vjcad';
// 获取坐标变换器
const trans: CoordinateTransform = Engine.trans;
// 世界坐标转用户坐标
const ucsPoint = trans.WcsToUcs(new Point2D(100, 100));
// 世界坐标转显示坐标
const dcsPoint = trans.WcsToDcs(new Point2D(100, 100));其他组件
| 属性 | 类型 | 说明 |
|---|---|---|
Engine.editor | Editor | 编辑控制器,处理用户输入 |
Engine.commandLine | CommandLine | 命令行组件 |
Engine.view | MainView | 主视图组件 |
Engine.eventManager | CadEventManager | 事件管理器,订阅/发布 CAD 事件 |
Engine.reactorManager | EntityReactorManager | 实体反应器管理器 |
Engine.sidePalettes | SidePalettes | 侧边面板容器 |
Engine.propertyPalette | PropertyPalette | 属性面板 |
Engine.service | Service | 后端服务接口 |
实体操作
添加实体
import { Engine, LineEnt, CircleEnt, Point2D } from 'vjcad';
// 创建实体
const line = new LineEnt(new Point2D(0, 0), new Point2D(100, 100));
const circle = new CircleEnt(new Point2D(50, 50), 30);
// 应用默认属性(图层、颜色等)
line.setDefaults();
circle.setDefaults();
// 方式一:使用 Engine.addEntities(推荐)
// 自动记录撤销,并刷新可选择实体列表
Engine.addEntities([line, circle]);
// 方式二:指定选项
Engine.addEntities(line, { recordUndo: false });
// 方式三:手动操作(不推荐,需要手动刷新可选择实体列表)
Engine.pcanvas.addEntity(line);
Engine.undoManager.added_undoMark([line]);
Engine.editor?.refreshRemain(); // 确保新实体可被选择实体可选择性
Engine.addEntities() 会自动调用 Engine.editor.refreshRemain() 刷新可选择实体列表, 确保新添加的实体可以立即被鼠标点击选择。如果使用其他方式添加实体(如直接调用 pcanvas.addEntity()), 需要手动调用 Engine.editor.refreshRemain() 才能使新实体可被选择。
删除实体
import { Engine, EntityBase } from 'vjcad';
// 删除单个实体(自动刷新可选择实体列表)
Engine.eraseEntities(entity);
// 删除多个实体
Engine.eraseEntities([entity1, entity2]);
// 不记录撤销
Engine.eraseEntities(entity, { recordUndo: false });提示
Engine.eraseEntities() 会自动调用 Engine.editor.refreshRemain() 刷新可选择实体列表, 确保被删除的实体从可选择列表中移除。
获取实体
import { Engine, EntityBase } from 'vjcad';
// 获取所有实体
const allEntities: EntityBase[] = Engine.getEntities();
// 根据类型获取实体
const lines = Engine.getEntitiesByType('LINE');
const circles = Engine.getEntitiesByType('CIRCLE');
const plines = Engine.getEntitiesByType('PLINE');
// 使用过滤函数获取实体
const redEntities = Engine.getEntities(ent => ent.color === 1);
const layer1Entities = Engine.getEntities(ent => ent.layer === '图层1');
// 获取当前选中的实体
const selected = Engine.getSelectedEntities();修改实体属性
import { Engine, EntityBase } from 'vjcad';
// 批量设置颜色(自动记录撤销)
Engine.setEntityColor(entities, 3); // 绿色
// 批量设置图层
Engine.setEntityLayer(entities, '标注层');
// 批量设置线型
Engine.setEntityLineType(entities, 'HIDDEN');
// 批量设置线型比例
Engine.setEntityLineTypeScale(entities, 2.0);
// 批量设置透明度(0-100)
Engine.setEntityTransparency(entities, 50);
// 手动修改实体时,先记录撤销
Engine.markModified(entity);
entity.color = 1; // setter 自动调用 setModified()图层操作
import { Engine, Layer } from 'vjcad';
// 获取所有图层
const layers: Layer[] = Engine.getLayers();
// 根据名称获取图层
const layer = Engine.getLayerByName('标注层');
// 获取当前图层名
const currentLayer: string = Engine.getCurrentLayer();
// 设置当前图层
Engine.setCurrentLayer('图层1');
// 创建新图层
const newLayer = Engine.createLayer('我的图层', {
color: 3, // 绿色
lineType: 'HIDDEN', // 虚线
layerOn: true // 打开
});
// 自动命名创建图层
const autoLayer = Engine.createLayer(); // 自动命名为 "图层1", "图层2" 等用户输入
获取点
import { Engine, PointInputOptions, InputStatusEnum, Point2D } from 'vjcad';
// 基本用法
const options = new PointInputOptions("指定点:");
const result = await Engine.getPoint(options);
if (result.status === InputStatusEnum.OK) {
const point = result.value as Point2D;
console.log(`点坐标: (${point.x}, ${point.y})`);
}
// 带基点的橡皮线
const options2 = new PointInputOptions("指定下一点:");
options2.basePoint = new Point2D(0, 0);
options2.useBasePoint = true;
// 带关键字
const options3 = new PointInputOptions("指定点或 [闭合(C)/放弃(U)]:");
options3.keywords = ["C", "U"];
const result3 = await Engine.getPoint(options3);
if (result3.status === InputStatusEnum.KEYWORD) {
console.log('用户输入了关键字:', result3.stringResult);
}获取选择集
import {
Engine,
SelectionSetInputOptions,
InputStatusEnum,
EntityBase
} from 'vjcad';
// 获取选择集
const options = new SelectionSetInputOptions("选择对象:");
const result = await Engine.getSelections(options);
if (result.status === InputStatusEnum.OK) {
const entities = result.value as EntityBase[];
console.log(`选中了 ${entities.length} 个实体`);
for (const entity of entities) {
console.log(`- ${entity.type}: ${entity.id}`);
}
}获取数值
import { Engine, RealInputOptions, IntegerInputOptions, InputStatusEnum } from 'vjcad';
// 获取实数
const realOptions = new RealInputOptions("输入半径:");
realOptions.defaultValue = 10;
const realResult = await Engine.getReal(realOptions);
if (realResult.status === InputStatusEnum.OK) {
const radius = realResult.value as number;
}
// 获取整数
const intOptions = new IntegerInputOptions("输入边数:");
intOptions.defaultValue = 6;
const intResult = await Engine.getInteger(intOptions);
if (intResult.status === InputStatusEnum.OK) {
const sides = intResult.value as number;
}获取字符串
import { Engine, StringInputOptions, InputStatusEnum } from 'vjcad';
const options = new StringInputOptions("输入文字内容:");
options.defaultValue = "默认文字";
const result = await Engine.getString(options);
if (result.status === InputStatusEnum.OK) {
const text = result.value as string;
}获取角点(窗口选择)
import { Engine, CornerInputOptions, InputStatusEnum, Point2D } from 'vjcad';
const options = new CornerInputOptions("指定对角点:");
options.basePoint = new Point2D(0, 0);
const result = await Engine.getCorner(options);
if (result.status === InputStatusEnum.OK) {
const corner = result.value as Point2D;
// 形成从 (0,0) 到 corner 的矩形区域
}视图控制
缩放
import { Engine, Point2D } from 'vjcad';
// 全图显示(缩放到所有实体范围)
Engine.zoomExtents();
// 全图显示(指定实体范围)
Engine.zoomExtents([entity1, entity2]);
// 带选项的全图显示
Engine.zoomExtents(entities, {
padding: { top: 20, bottom: 20, left: 20, right: 20 },
autoSetRenderOrigin: true // 自动设置渲染原点
});
// 缩放到指定实体(等同于 zoomExtents)
Engine.zoomToEntities([entity1, entity2]);
// 缩放以适应指定实体范围
Engine.zoomToFit(entities, {
top: 20, bottom: 20, left: 20, right: 20
});
// 获取实体边界框
const bounds = Engine.getBoundsByEntities(entities, "WCS");
// 获取屏幕范围(世界坐标系)
const screenBounds = Engine.getScreenBoundsWcs();
// 获取屏幕内的实体
const screenEntities = Engine.getScreenEntities();视图中心
import { Engine, Point2D } from 'vjcad';
// 设置视图中心到指定点
Engine.setCenter(new Point2D(100, 200));
// 设置视图中心但不重绘
Engine.setCenter(new Point2D(100, 200), false);
// 设置视图中心并带边距
Engine.setCenter(new Point2D(100, 200), true, {
top: 50, bottom: 0, left: 0, right: 0
});重绘与重生成
import { Engine } from 'vjcad';
// render: 最底层渲染,只执行GPU绘制
Engine.render();
// redraw: 更新视图变换(位置/缩放/旋转),然后调用render
Engine.redraw();
// regen: 局部更新,只重新渲染已setModified的实体(快)
Engine.regen();
// regen(true): 完全重绘,清除并重新绘制所有图形(慢)
Engine.regen(true);方法层级关系
regen(true) → 完全清除并重绘所有图形
↓
regen() → 只重绘已修改的实体(脏桶) → 调用 regenPartial()
↓
redraw() → 更新视图变换(位置/缩放/旋转) → 调用 render()
↓
render() → 调用 PIXI.renderer.render() 执行 GPU 绘制正确用法
修改实体属性后,setter 会自动调用 setModified() 标记为已修改,只需调用 regen() 进行局部刷新:
circle.radius = 45; // setter 自动调用 setModified()
Engine.regen(); // 局部更新(只重绘脏实体)背景与画布
import { Engine } from 'vjcad';
// 设置背景色(灰度值:0=黑色,255=白色)
Engine.setBgc(0); // 黑色背景
Engine.setBgc(255); // 白色背景
// 调整画布大小
Engine.resize(800, 600);清除操作
import { Engine } from 'vjcad';
// 清除夹点显示
Engine.clearGrip();
// 清除对象捕捉标记
Engine.clearOsnap();
// 清除高亮
Engine.clearHighLight();预览和高亮
import { Engine, LineEnt, Point2D } from 'vjcad';
// 绘制预览实体
const previewLine = new LineEnt(new Point2D(0, 0), new Point2D(100, 100));
Engine.drawPreviewEntity(previewLine);
// 批量预览
Engine.drawPreviewEntities([entity1, entity2]);
// 设置预览位置
Engine.setPreviewPosition(new Point2D(50, 50));
// 设置预览旋转
Engine.setPreviewRotation(Math.PI / 4);
// 清除预览
Engine.clearPreview();
// 高亮实体
Engine.highLightEntities([entity1, entity2]);
// 清除高亮
Engine.clearHighLight();坐标变换
WebCAD 使用三种坐标系:
- WCS (World Coordinate System):世界坐标系,绝对参考
- UCS (User Coordinate System):用户坐标系,可自定义的工作平面
- DCS (Display Coordinate System):显示坐标系,屏幕像素坐标
import { Engine, Point2D } from 'vjcad';
// Canvas 坐标转世界坐标(鼠标事件常用)
const wcsPoint = Engine.canvasToWcs(new Point2D(event.clientX, event.clientY));
// 世界坐标转用户坐标
const ucsPoint = Engine.wcsToUcs(wcsPoint);
// 用户坐标转世界坐标
const wcsPoint2 = Engine.ucsToWcs(ucsPoint);
// 世界坐标转显示坐标
const dcsPoint = Engine.wcsToDcs(wcsPoint);
// 使用 trans 对象进行更多转换
const trans = Engine.trans;
const ucsPoint2 = trans.WcsToUcs(wcsPoint);
const dcsPoint2 = trans.WcsToDcs(wcsPoint);
const wcsFromDcs = trans.DcsToWcs(dcsPoint);撤销记录
基本撤销操作
import { Engine } from 'vjcad';
// 记录添加实体的撤销
Engine.addedUndoMark([entity1, entity2]);
// 记录删除实体的撤销
Engine.erasedUndoMark([entity1]);
// 记录移动操作的撤销
Engine.movedUndoMark(entities, fromPoint, toPoint);
// 记录旋转操作的撤销
Engine.rotateUndoMark(entities, basePoint, angle);
// 记录缩放操作的撤销
Engine.scaledUndoMark(entities, basePoint, scale);
// 记录镜像操作的撤销
Engine.mirroredUndoMark(entities, point1, point2);撤销记录组
import { Engine } from 'vjcad';
// 开始撤销记录组(多个操作合并为一个撤销步骤)
Engine.startUndoRecord();
try {
// 执行多个操作
Engine.addEntities(entity1);
Engine.setEntityColor([entity1], 1);
Engine.setEntityLayer([entity1], '图层1');
} finally {
// 结束撤销记录组
Engine.endUndoRecord();
}
// 支持嵌套调用
Engine.startUndoRecord();
Engine.startUndoRecord(); // 嵌套
Engine.endUndoRecord();
Engine.endUndoRecord(); // 只有最外层会真正创建撤销组消息输出
import { Engine } from 'vjcad';
// 输出消息到命令行
Engine.writeMessage("操作完成");
Engine.writeMessage(`选中了 ${count} 个实体`);选择集操作
import { Engine, EntityBase } from 'vjcad';
// 设置选择集
Engine.ssSetFirst([entity1, entity2]);
// 清空选择集
Engine.ssSetFirst([]);
// 获取当前选择集
const selected: EntityBase[] = Engine.ssGetFirst();线段检测
detectLineAtPoint() 方法用于检测指定点附近的线段,支持直线实体(LINE)和多段线实体(PLINE)中的直线段。该功能常用于实现关联标注、智能捕捉等场景。
LineSegmentInfo 接口
interface LineSegmentInfo {
/** 线段的起点 */
startPoint: Point2D;
/** 线段的终点 */
endPoint: Point2D;
/** 原始实体(LINE 或 PLINE) */
entity: EntityBase;
/** 线段索引(对于多段线中的线段,表示该线段在多段线中的位置) */
segmentIndex: number;
/** 拾取点在线段上的类型 */
pointType: 'start' | 'end' | 'midpoint' | 'nearest';
/** 拾取点到线段的距离 */
distance: number;
/**
* 线性参数 t,表示拾取点在线段上的相对位置 (0-1)
* - t = 0 表示起点
* - t = 1 表示终点
* - t = 0.5 表示中点
*/
parameterT: number;
}基本用法
import { Engine, Point2D, LineSegmentInfo } from 'vjcad';
// 检测点附近的线段
const lineInfo: LineSegmentInfo | null = Engine.detectLineAtPoint(worldPoint);
if (lineInfo) {
console.log('检测到线段');
console.log('起点:', lineInfo.startPoint);
console.log('终点:', lineInfo.endPoint);
console.log('原始实体:', lineInfo.entity.type); // "LINE" 或 "PLINE"
console.log('线段索引:', lineInfo.segmentIndex); // 对于 LINE 始终为 0
console.log('点类型:', lineInfo.pointType); // 'start' | 'end' | 'midpoint' | 'nearest'
console.log('距离:', lineInfo.distance);
console.log('参数 t:', lineInfo.parameterT); // 0=起点, 1=终点, 0.5=中点
}
// 指定自定义容差(单位为世界坐标单位)
const lineInfo2 = Engine.detectLineAtPoint(worldPoint, 20);pointType 类型说明
| 类型 | 说明 |
|---|---|
'start' | 检测点靠近线段起点 |
'end' | 检测点靠近线段终点 |
'midpoint' | 检测点靠近线段中点 |
'nearest' | 检测点在线段上的最近点(非特殊点) |
应用示例:关联标注
import { Engine, Point2D, LineSegmentInfo, AlignedDimensionEnt } from 'vjcad';
async function createAssociatedDimension(pt1: Point2D, pt2: Point2D) {
// 检测第一个点附近的线段
const firstLine = Engine.detectLineAtPoint(pt1);
// 检测第二个点附近的线段
const secondLine = Engine.detectLineAtPoint(pt2);
// 创建标注
const dim = new AlignedDimensionEnt();
dim.setDefaults();
// 设置标注点
dim.firstPoint = pt1;
dim.secondPoint = pt2;
// 如果检测到线段,建立关联关系
if (firstLine) {
// 高亮显示关联的实体
Engine.highLightEntities([firstLine.entity]);
// 使用 pointType 建立关联('nearest' 不是有效的关联类型)
if (firstLine.pointType !== 'nearest') {
console.log(`第一点关联到线段的 ${firstLine.pointType}`);
}
}
if (secondLine) {
if (secondLine.pointType !== 'nearest') {
console.log(`第二点关联到线段的 ${secondLine.pointType}`);
}
}
Engine.addEntities(dim);
Engine.clearHighLight();
}应用示例:智能引线
import { Engine, Point2D, LineSegmentInfo } from 'vjcad';
async function createSmartLeader(arrowPoint: Point2D) {
// 检测箭头位置附近的线段
const snapInfo = Engine.detectLineAtPoint(arrowPoint);
if (snapInfo) {
// 高亮显示目标实体
Engine.pcanvas.highLightEntities([snapInfo.entity]);
// 根据 pointType 调整箭头位置到精确位置
let preciseArrowPoint: Point2D;
switch (snapInfo.pointType) {
case 'start':
preciseArrowPoint = snapInfo.startPoint.clone();
break;
case 'end':
preciseArrowPoint = snapInfo.endPoint.clone();
break;
case 'midpoint':
preciseArrowPoint = snapInfo.startPoint.clone();
preciseArrowPoint.x = (snapInfo.startPoint.x + snapInfo.endPoint.x) / 2;
preciseArrowPoint.y = (snapInfo.startPoint.y + snapInfo.endPoint.y) / 2;
break;
default:
// 使用 parameterT 计算最近点
preciseArrowPoint = new Point2D(
snapInfo.startPoint.x + snapInfo.parameterT * (snapInfo.endPoint.x - snapInfo.startPoint.x),
snapInfo.startPoint.y + snapInfo.parameterT * (snapInfo.endPoint.y - snapInfo.startPoint.y)
);
}
return preciseArrowPoint;
}
return arrowPoint;
}检测范围
- 默认容差为
Engine.APERTURE / Engine.currentSpace.zoom,即根据当前缩放级别自动调整 - 支持检测 LINE(直线)实体
- 支持检测 PLINE(多段线)实体中的直线段(弧段暂不支持)
- 使用空间索引优化搜索性能,适用于大量实体的场景
全局配置
import { Engine } from 'vjcad';
// 显示文件加载进度条
Engine.SHOWLOADPROGRESS = true;
// 使用 WASM 实现填充图案生成
Engine.USE_WASM_HATCH = true;
// 性能优先模式(禁用耗性能的特性)
Engine.performancePriorityMode = true;
// 延迟加载关闭图层
Engine.LAZYLOADCLOSEDLAYERS = true;
// 启用几何缓存
Engine.ENABLE_GEOMETRY_CACHE = true;
// 标注实体打开模式
Engine.OPEN_DIMENSION_AS_GROUP = false; // false=可编辑