mirror of https://gitee.com/cf-fz/WebCAD.git
!2773 功能: 图层
parent
d49806f684
commit
70fd7372a0
@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
//#region 避免无法进入测试 依赖错误导致的测试失败 ref file.test.ts
|
||||||
|
import { HostApplicationServices } from '../../src/ApplicationServices/HostApplicationServices';
|
||||||
|
import { DuplicateRecordCloning } from '../../src/Common/Status';
|
||||||
|
import { AllObjectData } from '../../src/DatabaseServices/AllObjectData';
|
||||||
|
AllObjectData;
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
import { Database } from '../../src/DatabaseServices/Database';
|
||||||
|
import { Entity } from '../../src/DatabaseServices/Entity/Entity';
|
||||||
|
import { Line } from '../../src/DatabaseServices/Entity/Line';
|
||||||
|
import { LayerTableRecord } from '../../src/DatabaseServices/LayerTableRecord';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1.新绘制的对象必须在当前层上
|
||||||
|
* 2.能够被序列化
|
||||||
|
*/
|
||||||
|
test('绘制的对象默认图层', () =>
|
||||||
|
{
|
||||||
|
let db = new Database(true, true, true);
|
||||||
|
|
||||||
|
let line = new Line;
|
||||||
|
|
||||||
|
db.ModelSpace.Append(line);
|
||||||
|
|
||||||
|
expect(line.Layer === db.DefaultLayer.Id).toBeTruthy();//图层等于默认图层
|
||||||
|
|
||||||
|
let layer = new LayerTableRecord();
|
||||||
|
layer.Name = "新图层1";
|
||||||
|
db.LayerTable.Add(layer);
|
||||||
|
|
||||||
|
db.LayerTable.Current = layer.Id;
|
||||||
|
|
||||||
|
line = new Line;
|
||||||
|
db.ModelSpace.Append(line);
|
||||||
|
expect(line.Layer === layer.Id).toBeTruthy();//图层应该等于当前图层
|
||||||
|
|
||||||
|
let id = line.Id.Index;
|
||||||
|
|
||||||
|
let db2 = new Database(false, false, true);
|
||||||
|
db2.FileRead(db.FileWrite());
|
||||||
|
|
||||||
|
let idnew = db2.GetObjectId(id);
|
||||||
|
|
||||||
|
(idnew.Object as Entity).Layer.Index;//?
|
||||||
|
|
||||||
|
expect((idnew.Object as Entity).Layer.Object.Name).toBe(layer.Name);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1.对于模块内的实体,由于之前没有图层,新绘入后,需要设置到当前图层
|
||||||
|
*/
|
||||||
|
test('模版文件的图层', () =>
|
||||||
|
{
|
||||||
|
let db1 = new Database(true, true, true);
|
||||||
|
HostApplicationServices.Database = db1;
|
||||||
|
|
||||||
|
let db2 = new Database(false, false, true);
|
||||||
|
|
||||||
|
let line = new Line;
|
||||||
|
db2.ModelSpace.Append(line);
|
||||||
|
line.Layer;
|
||||||
|
line.HasLayer;//?
|
||||||
|
|
||||||
|
db1.WblockCloneObejcts([line], db1.ModelSpace, new Map, DuplicateRecordCloning.Ignore);
|
||||||
|
|
||||||
|
db1.ModelSpace.Entitys[0].Layer.Object.Name;//?
|
||||||
|
|
||||||
|
let layer = new LayerTableRecord();
|
||||||
|
layer.Name = "新图层1";
|
||||||
|
db1.LayerTable.Add(layer);
|
||||||
|
db1.LayerTable.Current = layer.Id;
|
||||||
|
|
||||||
|
db1.WblockCloneObejcts([line], db1.ModelSpace, new Map, DuplicateRecordCloning.Ignore);
|
||||||
|
|
||||||
|
expect(db1.ModelSpace.Entitys[1].Layer.Object.Name).toBe(layer.Name);
|
||||||
|
});
|
@ -0,0 +1,58 @@
|
|||||||
|
import { AutoRecord } from "./AutoRecord";
|
||||||
|
import { Factory } from "./CADFactory";
|
||||||
|
import { CADFiler } from "./CADFiler";
|
||||||
|
import { CADObject } from "./CADObject";
|
||||||
|
import { SymbolTableRecord } from "./SymbolTableRecord";
|
||||||
|
|
||||||
|
@Factory
|
||||||
|
export class LayerTableRecord extends SymbolTableRecord
|
||||||
|
{
|
||||||
|
@AutoRecord ColorIndex: number = 7;
|
||||||
|
|
||||||
|
// @AutoRecord LineWeight: number = 0;
|
||||||
|
|
||||||
|
@AutoRecord IsOff = false;//关
|
||||||
|
|
||||||
|
@AutoRecord IsLocked = false;//锁定
|
||||||
|
|
||||||
|
// @AutoRecord IsFrozen = false;//冻结
|
||||||
|
|
||||||
|
// @AutoRecord IsHidden = false;//隐藏
|
||||||
|
|
||||||
|
// @AutoRecord Description = "";//描述
|
||||||
|
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region -------------------------File-------------------------
|
||||||
|
//对象从文件中读取数据,初始化自身
|
||||||
|
override ReadFile(file: CADFiler)
|
||||||
|
{
|
||||||
|
let ver = file.Read();
|
||||||
|
super.ReadFile(file);
|
||||||
|
|
||||||
|
this.ColorIndex = file.Read();
|
||||||
|
this.IsOff = file.Read();
|
||||||
|
this.IsLocked = file.Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
//对象将自身数据写入到文件.
|
||||||
|
override WriteFile(file: CADFiler)
|
||||||
|
{
|
||||||
|
file.Write(1);
|
||||||
|
super.WriteFile(file);
|
||||||
|
|
||||||
|
file.Write(this.ColorIndex);
|
||||||
|
file.Write(this.IsOff);
|
||||||
|
file.Write(this.IsLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
//局部撤销
|
||||||
|
override ApplyPartialUndo(undoData: CADObject)
|
||||||
|
{
|
||||||
|
super.ApplyPartialUndo(undoData);
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices";
|
||||||
|
import { Factory } from "../CADFactory";
|
||||||
|
import { CADFiler } from "../CADFiler";
|
||||||
|
import { CADObject } from "../CADObject";
|
||||||
|
import { HistorycRecord } from "../HistorycRecord";
|
||||||
|
import { ISerialize } from "../ISerialize";
|
||||||
|
import { LayerTableRecord } from "../LayerTableRecord";
|
||||||
|
import { ObjectId } from "../ObjectId";
|
||||||
|
import { SymbolTable } from "./SymbolTable";
|
||||||
|
|
||||||
|
@Factory
|
||||||
|
export class LayerTable extends SymbolTable
|
||||||
|
{
|
||||||
|
protected _Current: ObjectId<LayerTableRecord>;//默认当前图层
|
||||||
|
|
||||||
|
public get Current(): ObjectId<LayerTableRecord>
|
||||||
|
{
|
||||||
|
return this._Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set Current(id: ObjectId<LayerTableRecord>)//设置当前层
|
||||||
|
{
|
||||||
|
if (this._Current === id) return;
|
||||||
|
|
||||||
|
let undoData = this.UndoRecord();
|
||||||
|
if (undoData)
|
||||||
|
{
|
||||||
|
let hr = new HistorycRecord();
|
||||||
|
hr.undoData = new ObjectIdData(this._Current);
|
||||||
|
hr.redoData = new ObjectIdData(id);
|
||||||
|
undoData.WriteObjectHistoryPath(this, hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._Current = id;
|
||||||
|
HostApplicationServices.CurrentLayer = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用于描述图层结构的根节点 */
|
||||||
|
private _Root = new LayerNode("根节点", true);
|
||||||
|
|
||||||
|
public get Root(): LayerNode
|
||||||
|
{
|
||||||
|
return this._Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set Root(root: LayerNode)
|
||||||
|
{
|
||||||
|
if (this._Root === root) return;
|
||||||
|
|
||||||
|
let undoData = this.UndoRecord();
|
||||||
|
if (undoData)
|
||||||
|
{
|
||||||
|
let hr = new HistorycRecord();
|
||||||
|
hr.undoData = new ObjectTreeData(this._Root);
|
||||||
|
hr.redoData = new ObjectTreeData(root);
|
||||||
|
undoData.WriteObjectHistoryPath(this, hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._Root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region -------------------------File-------------------------
|
||||||
|
//对象从文件中读取数据,初始化自身
|
||||||
|
override ReadFile(file: CADFiler)
|
||||||
|
{
|
||||||
|
let ver = file.Read();
|
||||||
|
super.ReadFile(file);
|
||||||
|
|
||||||
|
this._Current = file.ReadObjectId() as ObjectId<LayerTableRecord>;
|
||||||
|
this._Root = file.ReadObject();
|
||||||
|
}
|
||||||
|
//对象将自身数据写入到文件.
|
||||||
|
override WriteFile(file: CADFiler)
|
||||||
|
{
|
||||||
|
file.Write(1);
|
||||||
|
super.WriteFile(file);
|
||||||
|
|
||||||
|
file.WriteObjectId(this._Current);
|
||||||
|
file.WriteObject(this._Root);
|
||||||
|
}
|
||||||
|
//局部撤销
|
||||||
|
override ApplyPartialUndo(undoData: CADObject)
|
||||||
|
{
|
||||||
|
if (undoData instanceof ObjectIdData)
|
||||||
|
{
|
||||||
|
this._Current = undoData.objectId as any;
|
||||||
|
HostApplicationServices.CurrentLayer = this._Current;
|
||||||
|
}
|
||||||
|
else if (undoData instanceof ObjectTreeData)
|
||||||
|
this._Root = undoData.data;
|
||||||
|
else
|
||||||
|
super.ApplyPartialUndo(undoData);
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用于描述图层结构的节点 */
|
||||||
|
@Factory
|
||||||
|
export class LayerNode implements ISerialize
|
||||||
|
{
|
||||||
|
children: LayerNode[];
|
||||||
|
|
||||||
|
constructor(public name: string, isHasChildren = false)
|
||||||
|
{
|
||||||
|
if (isHasChildren)
|
||||||
|
this.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadFile(f: CADFiler)
|
||||||
|
{
|
||||||
|
this.name = f.ReadString();
|
||||||
|
const count = f.Read();
|
||||||
|
if (count !== -1)
|
||||||
|
{
|
||||||
|
this.children = [];
|
||||||
|
for (let i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const child = new LayerNode("");
|
||||||
|
child.ReadFile(f);
|
||||||
|
this.children.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteFile(f: CADFiler)
|
||||||
|
{
|
||||||
|
f.WriteString(this.name);
|
||||||
|
if (!this.children)
|
||||||
|
f.Write(-1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f.Write(this.children.length);
|
||||||
|
for (const child of this.children)
|
||||||
|
child.WriteFile(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录当前id的序列化数据
|
||||||
|
*/
|
||||||
|
@Factory
|
||||||
|
export class ObjectIdData implements ISerialize
|
||||||
|
{
|
||||||
|
ReadFile(file: CADFiler): this
|
||||||
|
{
|
||||||
|
this.objectId = file.ReadObjectId();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
WriteFile(file: CADFiler): this
|
||||||
|
{
|
||||||
|
file.WriteObjectId(this.objectId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
constructor(public objectId: ObjectId) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 记录树状结构的序列化数据*/
|
||||||
|
@Factory
|
||||||
|
export class ObjectTreeData implements ISerialize
|
||||||
|
{
|
||||||
|
ReadFile(file: CADFiler): this
|
||||||
|
{
|
||||||
|
this.data = file.ReadObject();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
WriteFile(file: CADFiler): this
|
||||||
|
{
|
||||||
|
file.WriteObject(this.data);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
constructor(public data: LayerNode) { }
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
import { end } from "xaop";
|
||||||
|
import { app } from "../ApplicationServices/Application";
|
||||||
|
import { CommandNames } from "../Common/CommandNames";
|
||||||
|
import { CommandHistoryRecord } from "../DatabaseServices/CommandHistoryRecord";
|
||||||
|
import { LayerTableRecord } from "../DatabaseServices/LayerTableRecord";
|
||||||
|
import { LayerTable } from "../DatabaseServices/Tables/LayerTable";
|
||||||
|
import { LayerTopStore } from "../UI/Components/ToolBar/Layer/LayerPanel";
|
||||||
|
import { LayerStore } from "../UI/Components/ToolBar/Layer/State/Store";
|
||||||
|
import { DataToViewForLayer } from "../UI/Components/ToolBar/Layer/State/Transform";
|
||||||
|
|
||||||
|
|
||||||
|
/** 图层反应器 */
|
||||||
|
export class LayerReactor
|
||||||
|
{
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
//解析撤销重做
|
||||||
|
const ParseFunction = (isUndo = true) =>
|
||||||
|
{
|
||||||
|
return (cmdName: string, historyRec: CommandHistoryRecord) =>
|
||||||
|
{
|
||||||
|
if (!app.Database.LayerTable || !app.Database.LayerTable.Current) return;
|
||||||
|
// 图层UI随图层表更新
|
||||||
|
for (const [k, v] of historyRec.HistoryList)
|
||||||
|
{
|
||||||
|
const o = k.Object;
|
||||||
|
if (o instanceof LayerTableRecord || o instanceof LayerTable)
|
||||||
|
{
|
||||||
|
DataToViewForLayer.UpdateAll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParseUndo = ParseFunction(true);
|
||||||
|
const ParseRedo = ParseFunction(false);
|
||||||
|
|
||||||
|
end(app.Database.hm, app.Database.hm.RedoEvent, ParseRedo);
|
||||||
|
end(app.Database.hm, app.Database.hm.UndoEvent, ParseUndo);
|
||||||
|
|
||||||
|
// 新建图纸时初始化图层UI
|
||||||
|
const InitLayer = () =>
|
||||||
|
{
|
||||||
|
const layerStore = LayerStore.GetInstance();
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
DataToViewForLayer.UpdateAll();
|
||||||
|
layerTopStore.setCurrentLayerValue(layerStore.currentLayer.name);
|
||||||
|
};
|
||||||
|
end(app, app.CreateDocument, () => InitLayer());
|
||||||
|
|
||||||
|
// 打开图纸时加载图层UI
|
||||||
|
end(app, app.OpenFile, () => InitLayer());
|
||||||
|
|
||||||
|
// 插入图纸/插入模板时更新图层UI
|
||||||
|
app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) =>
|
||||||
|
{
|
||||||
|
if (cmdName === CommandNames.Insert || cmdName === CommandNames.InsertModule || cmdName === CommandNames.EditTemplate)
|
||||||
|
{
|
||||||
|
DataToViewForLayer.UpdateRootByTable();
|
||||||
|
DataToViewForLayer.UpdateAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
.colorHoverActive {
|
||||||
|
border-color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorHover:hover {
|
||||||
|
border-color: #fff !important;
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
import { Button, Classes } from "@blueprintjs/core";
|
||||||
|
import { observable } from "mobx";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import React from "react";
|
||||||
|
import { app } from "../../../../../ApplicationServices/Application";
|
||||||
|
import { ColorPalette } from "../../../../../Common/ColorPalette";
|
||||||
|
import { ModalContainer, ModalHeader } from "../../../Modal/ModalContainer";
|
||||||
|
import "./Color.css";
|
||||||
|
import { ColorAPI } from "./ColorAPI";
|
||||||
|
|
||||||
|
/** 颜色选择的弹窗 */
|
||||||
|
@observer
|
||||||
|
export class ColorDialog extends React.Component<{ colorIndex: number, onConfirm?: (colorIndex?: number) => void; }> {
|
||||||
|
constructor(props)
|
||||||
|
{
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 图层名称输入框的DOM */
|
||||||
|
_ColorManagerRef = React.createRef<ColorManager>();
|
||||||
|
|
||||||
|
// 视图渲染(这是主要部分,上面做的都是一些参数的初始化)
|
||||||
|
public render()
|
||||||
|
{
|
||||||
|
const { colorIndex, onConfirm } = this.props;
|
||||||
|
return (
|
||||||
|
<ModalContainer className="headCeilingContourManage">
|
||||||
|
<ModalHeader
|
||||||
|
title={"颜色选择器"}
|
||||||
|
icon="bold"
|
||||||
|
close={() => app.Editor.ModalManage.Destory()}
|
||||||
|
/>
|
||||||
|
<div className={Classes.DIALOG_BODY} style={{ width: "500px", height: "auto" }}>
|
||||||
|
<ColorManager ref={this._ColorManagerRef} colorIndex={colorIndex} />
|
||||||
|
</div>
|
||||||
|
<div className={Classes.DIALOG_FOOTER} >
|
||||||
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
|
<Button
|
||||||
|
className={Classes.INTENT_PRIMARY}
|
||||||
|
text="确定"
|
||||||
|
onClick={() =>
|
||||||
|
{
|
||||||
|
if (onConfirm) onConfirm(this._ColorManagerRef.current.colorIndex);
|
||||||
|
app.Editor.ModalManage.Destory();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className={Classes.INTENT_DANGER}
|
||||||
|
text="取消"
|
||||||
|
onClick={() => app.Editor.ModalManage.Destory()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalContainer >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 颜色选择器 */
|
||||||
|
@observer
|
||||||
|
class ColorManager extends React.Component<{ colorIndex: number; }> {
|
||||||
|
constructor(props)
|
||||||
|
{
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 当前选择的颜色索引 */
|
||||||
|
@observable
|
||||||
|
colorIndex = this.props.colorIndex;
|
||||||
|
|
||||||
|
// 视图渲染(这是主要部分,上面做的都是一些参数的初始化)
|
||||||
|
public render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div style={{ width: "100%", borderRadius: "3px", overflow: "hidden", display: "flex", flexWrap: "wrap" }}>
|
||||||
|
{ColorPalette.slice(0, 256).map((color, index) => <div className={"colorHover" + (this.colorIndex === index ? " colorHoverActive" : "")} style={{
|
||||||
|
width: "25px", height: "25px", border: "1px solid #000", display: "flex", justifyContent: "center", alignItems: "center", cursor: "pointer",
|
||||||
|
background: ColorAPI.GetColor(index), color: ColorAPI.GetGrayColor(index)
|
||||||
|
}} title={ColorAPI.GetColor(index)} onClick={() =>
|
||||||
|
{
|
||||||
|
this.colorIndex = index;
|
||||||
|
}}>{index}</div>)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 颜色块 */
|
||||||
|
export const ColorBlock = (props: { colorIndex: number; }) => <div style={{ width: "15px", height: "15px", background: ColorAPI.GetColor(props.colorIndex), border: "1px solid #000", marginRight: "5px" }}></div>;
|
@ -0,0 +1,20 @@
|
|||||||
|
import { ColorPalette } from "../../../../../Common/ColorPalette";
|
||||||
|
|
||||||
|
export class ColorAPI
|
||||||
|
{
|
||||||
|
/** 获取WebCAD中的颜色 */
|
||||||
|
static GetColor = (colorIndex: number) => `rgb(${ColorPalette[colorIndex][0]}, ${ColorPalette[colorIndex][1]}, ${ColorPalette[colorIndex][2]})`;
|
||||||
|
|
||||||
|
/** 获取WebCAD中的颜色索引(头尾相连) */
|
||||||
|
static GetColorIndex = (index: number) => index % 7 + 1;
|
||||||
|
|
||||||
|
/** RGB转黑白色 */
|
||||||
|
static Rgb2Gray = (r: number, g: number, b: number) => (r * 0.299) + (g * 0.587) + (b * 0.114) > 128 ? 255 : 0;
|
||||||
|
|
||||||
|
/** 获取WebCAD中的颜色对应的反向黑白色 */
|
||||||
|
static GetGrayColor(colorIndex: number)
|
||||||
|
{
|
||||||
|
const value = Math.abs(255 - ColorAPI.Rgb2Gray(ColorPalette[colorIndex][0], ColorPalette[colorIndex][1], ColorPalette[colorIndex][2]));
|
||||||
|
return `rgb(${value},${value},${value})`;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
/** 创建一个SVG图标 */
|
||||||
|
export const IconSVG = (props: { name: string, size?: number, color?: string; }) =>
|
||||||
|
{
|
||||||
|
const { name, size = 40, color = "#000000" } = props;
|
||||||
|
if (name === "图层特性")
|
||||||
|
return <svg viewBox="0 0 1024 1024" p-id="7511" width={`${size}`} height={`${size}`}>
|
||||||
|
<path d="M83.914105 781.473684h485.052632l323.368421-363.789473h-485.052632l-323.368421 363.789473z" fill="#E7E7E7" p-id="7512"></path>
|
||||||
|
<path d="M53.894737 794.947368L401.219368 404.210526h521.108211L575.002947 794.947368H53.894737zM862.315789 431.157895H413.318737L113.906526 768h448.997053L862.315789 431.157895z" fill="#131418" p-id="7513"></path>
|
||||||
|
<path d="M83.914105 619.789474h485.052632l323.368421-363.789474h-485.052632l-323.368421 363.789474z" fill="#E7E7E7" p-id="7514"></path>
|
||||||
|
<path d="M53.894737 633.263158L401.219368 242.526316h521.108211L575.002947 633.263158H53.894737zM862.315789 269.473684H413.318737L113.906526 606.315789h448.997053L862.315789 269.473684z" fill="#131418" p-id="7515"></path>
|
||||||
|
<path d="M83.914105 458.105263h485.052632l323.368421-363.789474h-485.052632l-323.368421 363.789474z" fill="#E7E7E7" p-id="7516"></path>
|
||||||
|
<path d="M53.894737 471.578947h521.10821L922.327579 80.842105H401.219368L53.894737 471.578947zM862.315789 107.789474L562.903579 444.631579H113.906526L413.318737 107.789474H862.315789z" fill="#131418" p-id="7517"></path>
|
||||||
|
<path d="M622.861474 471.578947h323.368421v458.105264h-323.368421v-458.105264z" fill="#FFFFFF" p-id="7518"></path>
|
||||||
|
<path d="M959.703579 943.157895h-350.31579V458.105263h350.31579v485.052632z m-26.947368-26.947369V485.052632h-296.421053v431.157894h296.421053z" fill="#131418" p-id="7519"></path>
|
||||||
|
<path d="M676.756211 525.473684h215.578947v161.684211h-215.578947v-161.684211z" fill="#50A5FF" p-id="7520"></path>
|
||||||
|
<path d="M905.808842 700.631579h-242.526316v-188.631579h242.526316v188.631579z m-26.947368-26.947368v-134.736843h-188.631579v134.736843h188.631579z" fill="#131418" p-id="7521"></path>
|
||||||
|
<path d="M690.229895 768h188.631579v26.947368h-188.631579v-26.947368zM690.229895 848.842105h188.631579v26.947369h-188.631579v-26.947369z" fill="#767676" p-id="7522"></path>
|
||||||
|
<path d="M744.124632 741.052632v80.842105h-26.947369v-80.842105h26.947369zM838.440421 821.894737v80.842105h-26.947368v-80.842105h26.947368z" fill="#767676" p-id="7523"></path>
|
||||||
|
</svg>;
|
||||||
|
if (name === "锁定选定对象图层")
|
||||||
|
return <svg viewBox="0 0 1024 1024" p-id="4707" width={`${size}`} height={`${size}`}>
|
||||||
|
<path d="M932.3776 0a38.4 38.4 0 0 1 33.3696 57.3952l-378.7008 665.6A38.4 38.4 0 0 1 553.664 742.4H40.4224a38.4 38.4 0 0 1-33.3696-57.3952l378.7008-665.6A38.4 38.4 0 0 1 419.136 0h513.2416z m-88.064 89.6H448.9088L128.4608 652.8h395.4176L844.3136 89.6zM924.7744 748.9664v-78.848c0-66.0224-65.1392-119.7184-131.1616-119.7184-66.0224 0-131.2128 53.696-131.2128 119.7184v78.848h-56.832a29.568 29.568 0 0 0-29.568 29.568v215.8592A29.568 29.568 0 0 0 605.568 1024h376.0896A29.5424 29.5424 0 0 0 1011.2 994.3936V778.5344a29.568 29.568 0 0 0-29.568-29.568h-56.8576zM810.9312 943.488c0 2.0096-1.8176 3.712-4.0448 3.712h-26.5216c-2.2528 0-4.0704-1.7024-4.0704-3.712v-45.056C763.8272 892.6208 755.2 880.896 755.2 867.2c0-19.4176 17.2032-35.2 38.3872-35.2C814.7968 832 832 847.7824 832 867.2c0.0256 13.696-8.6016 25.408-21.056 31.232v45.056zM716.8 755.2v-78.3744C716.8 635.3536 760.32 601.6 800.0256 601.6S883.2 635.3664 883.2 676.8256V755.2H716.8z" fill={`${color}`} p-id="4708"></path>
|
||||||
|
</svg>;
|
||||||
|
if (name === "解锁选定对象图层")
|
||||||
|
return <svg viewBox="0 0 1024 1024" p-id="5919" width={`${size}`} height={`${size}`}>
|
||||||
|
<path d="M932.307677 0a38.39712 38.39712 0 0 1 33.367097 57.390896l-378.672399 665.550083A38.39712 38.39712 0 0 1 553.622478 742.344324H40.419369a38.39712 38.39712 0 0 1-33.367098-57.390896l378.6724-665.550083A38.39712 38.39712 0 0 1 419.104567 0h513.20311z m-88.057396 89.593281H448.875134L128.451166 652.751044h395.387946L844.250281 89.593281zM721.123516 746.120041H891.581131v-2.150239h45.922956v2.150239h56.853336a29.693773 29.693773 0 0 1 29.501788 27.978702L1023.923206 994.024648c0 15.896408-12.210284 28.861835-27.671525 29.834563l-1.86866 0.063995H618.321626a29.693773 29.693773 0 0 1-29.501787-28.0043L588.755843 994.024648V775.980201c0-15.87081 12.235882-28.823438 27.697123-29.808964l58.696398-0.051196v-126.032148c0-65.633477 63.137665-119.19746 128.067195-120.886933L806.339525 499.162563c64.967927 0 129.078319 52.52726 131.100567 117.763968l0.051196 3.161362v42.697598c-3.263755 15.46124-10.636002 23.191861-22.116741 23.191861s-19.416144-7.73062-23.806215-23.191861v-40.713746c0-40.227383-42.697598-73.146514-82.6562-74.490414l-2.547009-0.051196c-39.805015 0-83.398545 32.074394-85.190411 71.981802l-0.063995 126.608104zM806.339525 819.138565C785.144314 819.138565 767.942404 836.67325 767.942404 858.239632c0 14.386121 7.692223 26.775592 19.044972 33.571882l2.047846 1.151914v50.044246c0 1.958253 1.382296 3.647726 3.250957 4.031698l0.819138 0.089593h26.519611a4.095693 4.095693 0 0 0 3.967703-3.302152l0.076794-0.819139v-50.044246A38.960278 38.960278 0 0 0 844.736645 858.226833C844.736645 836.67325 827.534735 819.138565 806.326725 819.138565z" fill={`${color}`} p-id="5920"></path>
|
||||||
|
</svg>;
|
||||||
|
if (name === "置为当前图层")
|
||||||
|
return <svg viewBox="0 0 1024 1024" p-id="2842" width={`${size}`} height={`${size}`}>
|
||||||
|
<path d="M942.933333 311.466667l-384-192c-25.6-17.066667-55.466667-17.066667-81.066666 0l-384 192c0 4.266667-4.266667 8.533333-8.533334 8.533333-4.266667 17.066667 0 34.133333 12.8 38.4L234.666667 426.666667l-115.2 59.733333c-12.8 8.533333-21.333333 21.333333-21.333334 34.133333 0 12.8 8.533333 29.866667 21.333334 34.133334l98.133333 51.2-98.133333 51.2c-12.8 8.533333-21.333333 21.333333-21.333334 34.133333 0 12.8 8.533333 29.866667 21.333334 34.133333l358.4 179.2c12.8 8.533333 25.6 12.8 38.4 12.8 12.8 0 29.866667-4.266667 42.666666-12.8l358.4-179.2c12.8-8.533333 21.333333-21.333333 21.333334-34.133333 0-12.8-8.533333-29.866667-21.333334-34.133333l-98.133333-51.2 98.133333-51.2c12.8-8.533333 21.333333-21.333333 21.333334-34.133334 0-12.8-8.533333-29.866667-21.333334-34.133333L806.4 426.666667l136.533333-68.266667c4.266667-4.266667 8.533333-4.266667 8.533334-8.533333 4.266667-17.066667 0-34.133333-8.533334-38.4z m-81.066666 379.733333l-328.533334 166.4c-8.533333 4.266667-17.066667 4.266667-25.6 0l-328.533333-166.4 106.666667-55.466667 196.266666 98.133334c12.8 8.533333 25.6 12.8 38.4 12.8 12.8 0 29.866667-4.266667 42.666667-12.8l196.266667-98.133334 102.4 55.466667z m0-170.666667l-106.666667 55.466667-64 29.866667-162.133333 81.066666c-8.533333 4.266667-17.066667 4.266667-25.6 0L341.333333 605.866667l-64-29.866667L170.666667 520.533333l128-64 183.466666 93.866667c25.6 17.066667 55.466667 17.066667 81.066667 0l183.466667-93.866667 115.2 64z" p-id="2843"></path>
|
||||||
|
</svg>;
|
||||||
|
if (name === "特性匹配")
|
||||||
|
return <svg viewBox="0 0 1094 1024" p-id="1559" width={`${size}`} height={`${size}`}>
|
||||||
|
<path d="M161.684211 80.842105h502.218105v697.532632H161.684211V80.842105z" fill="#E7E7E7" p-id="1560"></path>
|
||||||
|
<path d="M677.376 67.368421H148.210526v724.48h529.165474V67.368421zM175.157895 764.901053V94.315789h475.270737v670.585264H175.157895z" fill="#131418" p-id="1561"></path>
|
||||||
|
<path d="M245.382737 162.896842h334.821052v246.191158H245.382737V162.896842z" fill="#50A5FF" p-id="1562"></path>
|
||||||
|
<path d="M593.677474 149.423158H231.909053v273.138526h361.768421V149.423158zM258.856421 395.614316V176.370526h307.873684v219.24379H258.856421z" fill="#131418" p-id="1563"></path>
|
||||||
|
<path d="M266.320842 518.386526h292.97179v26.947369H266.320842v-26.947369zM266.320842 641.482105h292.97179v26.947369H266.320842v-26.947369z" fill="#767676" p-id="1564"></path>
|
||||||
|
<path d="M335.117474 463.252211v123.095578h-26.947369v-123.095578h26.947369zM481.603368 586.374737v123.068631h-26.947368V586.374737h26.947368z" fill="#767676" p-id="1565"></path>
|
||||||
|
<path d="M779.502579 530.19464q-19.236049 0.329671-31.830599 13.844086l-64.639793 58.563144-24.159292-20.798617q-14.315861-12.324455-32.751-12.016437-20.26782 0.330366-33.190037 15.340577l-55.556745 64.533697q-32.515594 29.21977-79.822816 47.163363l-42.345993 16.063216 274.370322 236.204072q22.117087 19.040492 49.796246 19.187939 31.864668 0.159407 51.080118-24.473884 26.2643-33.605864 40.709116-83.716328l34.547153-40.12934q12.904636-14.989789 10.256069-35.084319-2.436203-18.276053-16.772486-30.61809l-24.13887-20.781036 48.284566-72.607721q11.488919-14.501805 8.955056-33.573087-2.436203-18.276053-16.772486-30.61809l-63.247107-54.449126q-14.336283-12.342036-32.771422-12.034019z m-96.039387 108.335947l83.288987-75.434543c6.680874-7.760381 19.217515-7.990525 27.958155-0.465751l63.247107 54.449126c8.74064 7.524774 10.376906 19.956305 3.696032 27.716686l-62.213425 93.578392 42.171546 36.305278c8.74064 7.524774 10.374066 19.918302 3.675609 27.699105l-38.45019 44.663036c-8.92788 33.169791-21.585486 59.644028-37.611976 80.160049-15.258597 19.541444-43.278872 17.642468-62.067163 1.46772L467.096607 722.00211c9.530526-3.63592 18.713877-7.570721 27.506367-11.877569a268.611368 268.611368 0 0 0 50.985578-32.129057 236.058947 236.058947 0 0 0 20.134005-18.2244l-0.878148-0.755993 48.489083-56.324031c6.698456-7.780803 19.197093-8.008107 27.937733-0.483332l42.171545 36.305278z" fill="#131418" p-id="1566"></path>
|
||||||
|
<path d="M684.504717 639.427231l83.452363-75.293894c6.680874-7.760381 19.299203-7.9202 28.162376-0.289938l64.125255 55.20512c8.883594 7.647843 10.601549 20.149699 3.920675 27.91008l-62.050049 93.719041 42.763786 36.815135c8.84275 7.612681 10.598708 20.111695 3.900252 27.892498L800.290292 861.709303 565.089474 659.226065l48.489083-56.32403c6.698456-7.780803 19.299203-7.9202 28.162375-0.289938l42.763785 36.815134z" fill="#FFFFFF" p-id="1567"></path>
|
||||||
|
<path d="M591.245762 628.265156l222.075951 207.113938c-8.424421 45.017227-22.335978 72.865423-41.415168 93.95358-16.58319 18.436667-45.07939 16.305757-63.867682 0.131008L466.73185 721.723651c53.780597-20.300056 95.614828-51.133585 124.534334-93.440914z" fill="#FAD97F" p-id="1568"></path>
|
||||||
|
</svg>;
|
||||||
|
};
|
@ -0,0 +1,47 @@
|
|||||||
|
.layer-select {
|
||||||
|
position: relative;
|
||||||
|
width: 150px;
|
||||||
|
font-size: 14px;
|
||||||
|
z-index: 29;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 当前选择项 */
|
||||||
|
.layer-select-current {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 5px;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-select-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉选项 */
|
||||||
|
.layer-select-options {
|
||||||
|
overflow-y: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 30px;
|
||||||
|
left: 0;
|
||||||
|
padding: 5px;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 400px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-select-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-select-option:hover {
|
||||||
|
background: rgba(200, 210, 220, 0.5);
|
||||||
|
}
|
@ -0,0 +1,278 @@
|
|||||||
|
import { app } from "../../../../ApplicationServices/Application";
|
||||||
|
import { CommandNames } from "../../../../Common/CommandNames";
|
||||||
|
import { Log } from "../../../../Common/Log";
|
||||||
|
import { Entity } from "../../../../DatabaseServices/Entity/Entity";
|
||||||
|
import { LayerTableRecord } from "../../../../DatabaseServices/LayerTableRecord";
|
||||||
|
import { AmbientLight } from "../../../../DatabaseServices/Lights/AmbientLight";
|
||||||
|
import { DirectionalLight } from "../../../../DatabaseServices/Lights/DirectionalLight";
|
||||||
|
import { HemisphereLight } from "../../../../DatabaseServices/Lights/HemisphereLight";
|
||||||
|
import { ObjectId } from "../../../../DatabaseServices/ObjectId";
|
||||||
|
import { ViewportEntity } from "../../../../DatabaseServices/ViewportEntity";
|
||||||
|
import { CommandWrap } from "../../../../Editor/CommandMachine";
|
||||||
|
import { LayerAPI } from "./layerAPI";
|
||||||
|
import { LayerTopStore } from "./LayerPanel";
|
||||||
|
import { LayerAction, TreeAction } from "./State/Action";
|
||||||
|
import { LayerStore } from "./State/Store";
|
||||||
|
import { ViewToDataForLayer } from "./State/Transform";
|
||||||
|
import type { ILayerNode } from "./State/Type";
|
||||||
|
|
||||||
|
/** 图层命令 */
|
||||||
|
export class LayerCMD
|
||||||
|
{
|
||||||
|
/** 创建图层 */
|
||||||
|
static AppendLayer = () =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
// 更新View层数据
|
||||||
|
const node = layerAPI.AppendFile();
|
||||||
|
layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex;
|
||||||
|
// 更新Data层数据
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
if (node)
|
||||||
|
ViewToDataForLayer.AppendLayer(node);
|
||||||
|
}, CommandNames.AppendLayer);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 创建文件夹 */
|
||||||
|
static AppendLayerFolder = () =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
// 更新View层数据
|
||||||
|
const node = layerAPI.AppendFolder();
|
||||||
|
// 更新Data层数据
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
if (node)
|
||||||
|
ViewToDataForLayer.AppendLayer(node);
|
||||||
|
}, CommandNames.AppendLayerFolder);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除图层 */
|
||||||
|
static RemoveLayer = (node: ILayerNode, moveWhere?: string) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
// 更新View层数据
|
||||||
|
if (!node.children)
|
||||||
|
{
|
||||||
|
layerAPI.RemoveFile(node);
|
||||||
|
if (node.isCurrent)
|
||||||
|
{
|
||||||
|
const layerAction = new LayerAction(LayerStore.GetInstance());
|
||||||
|
const normal = layerAction.FindNodeByName("默认");
|
||||||
|
layerTopStore.featureMatchOptions[0].colorIndex = normal.colorIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
layerAPI.RemoveFolder(node);
|
||||||
|
// 更新Data层数据
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.RemoveLayer(node, moveWhere);
|
||||||
|
}, !node.children ? CommandNames.RemoveLayer : CommandNames.RemoveLayerFolder);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 置为当前图层 */
|
||||||
|
static SetCurrentLayer = (node: ILayerNode) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
if (node.isCurrent)
|
||||||
|
{
|
||||||
|
Log("已经是当前图层");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layerAPI.SetCurrentFile(node);
|
||||||
|
layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex;
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.SetCurrentLayer();
|
||||||
|
}, CommandNames.SetCurrentLayer);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改实体所在的图层 */
|
||||||
|
static PutEntitysInLayer = (ens: Entity[], node: ILayerNode) =>
|
||||||
|
{
|
||||||
|
const layerTable = app.Database.LayerTable;
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
if (!layerTable.Has(node.name))
|
||||||
|
return;
|
||||||
|
const layer = layerTable.GetAt(node.name) as LayerTableRecord;
|
||||||
|
layerTopStore.setColorIndex(node.colorIndex, 0);
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
for (const en of ens)
|
||||||
|
en.Layer = layer.Id;
|
||||||
|
}, CommandNames.PutEntitysInLayer);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 设置是否显示 */
|
||||||
|
static UpdateShow = (node: ILayerNode) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
if (!node.children)
|
||||||
|
layerAPI.UpdateShowFile(node, !node.isOff);
|
||||||
|
else
|
||||||
|
layerAPI.UpdateShowFolder(node, !node.isOff);
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.UpdateShow(node);
|
||||||
|
}, CommandNames.UpdateShow);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 设置是否锁定 */
|
||||||
|
static UpdateLock = (node: ILayerNode, isLock: boolean) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
if (!node.children)
|
||||||
|
layerAPI.UpdateLockFile(node, isLock);
|
||||||
|
else
|
||||||
|
layerAPI.UpdateLockFolder(node, isLock);
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.UpdateLock(node);
|
||||||
|
}, CommandNames.UpdateLock);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 设置是否视口冻结 */
|
||||||
|
static UpdateViewPoint = (node: ILayerNode) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
if (!node.children)
|
||||||
|
layerAPI.UpdateViewportOffFile(node, !node.isViewportOff);
|
||||||
|
else
|
||||||
|
layerAPI.UpdateViewportOffFolder(node, !node.isViewportOff);
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.UpdateViewPoint(node);
|
||||||
|
}, CommandNames.UpdateViewPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 设置颜色 */
|
||||||
|
static UpdateColor = (node: ILayerNode, colorIndex: number) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
layerAPI.UpdateColorFile(node, colorIndex);
|
||||||
|
if (node.isCurrent)
|
||||||
|
layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex;
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.UpdateColor(node);
|
||||||
|
}, CommandNames.UpdateColor);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重命名图层 */
|
||||||
|
static RenameLayer = (node: ILayerNode, name: string) =>
|
||||||
|
{
|
||||||
|
const layerAPI = new LayerAPI(LayerStore.GetInstance());
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
const oldName = node.name;
|
||||||
|
layerAPI.RenameNode(node, name);
|
||||||
|
if (layerTopStore.currentLayerValue === node.name)
|
||||||
|
layerTopStore.currentLayerValue = name;
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.RenameLayer(oldName, name);
|
||||||
|
}, !node.children ? CommandNames.RenameLayer : CommandNames.RenameLayerFolder);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 移动图层 */
|
||||||
|
static MoveLayer = (node: ILayerNode, moveWhere: string, isFolder) =>
|
||||||
|
{
|
||||||
|
if (moveWhere === node.name)
|
||||||
|
return;
|
||||||
|
const layerStore = LayerStore.GetInstance();
|
||||||
|
TreeAction.RemoveNode(layerStore.data, node.name);
|
||||||
|
if (moveWhere === "--LAST")
|
||||||
|
layerStore.data.push(node);
|
||||||
|
else if (isFolder)
|
||||||
|
TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.name === moveWhere).children.push(node);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const indexs = TreeAction.FindIndexsByName(layerStore.data, moveWhere);
|
||||||
|
TreeAction.InsertNode(layerStore.data, node, indexs);
|
||||||
|
}
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ViewToDataForLayer.MoveLayer(node);
|
||||||
|
}, !node.children ? CommandNames.MoveLayer : CommandNames.MoveLayerFolder);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选中图层中的实体 */
|
||||||
|
export const SelectLayerEntitys = (data: ILayerNode) =>
|
||||||
|
{
|
||||||
|
const layerTable = app.Database.LayerTable;
|
||||||
|
const nodeSet: Set<ObjectId<LayerTableRecord>> = new Set();
|
||||||
|
// 获取ID
|
||||||
|
if (data.children && data.children.length > 0)
|
||||||
|
{
|
||||||
|
TreeAction.UpdateNode(data.children, (node: ILayerNode) =>
|
||||||
|
{
|
||||||
|
if (!layerTable.Has(node.name))
|
||||||
|
return;
|
||||||
|
const layer = layerTable.GetAt(node.name) as LayerTableRecord;
|
||||||
|
nodeSet.add(layer.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!layerTable.Has(data.name))
|
||||||
|
return;
|
||||||
|
const layer = layerTable.GetAt(data.name) as LayerTableRecord;
|
||||||
|
nodeSet.add(layer.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始选择
|
||||||
|
const ens: Entity[] = [];
|
||||||
|
if (app.Viewer.isLayout)
|
||||||
|
{
|
||||||
|
const CurrentViewport = app.Viewer.CurrentViewport;
|
||||||
|
if (CurrentViewport)
|
||||||
|
ens.push(...app.Viewer.CurrentViewport.ShowObjects.map((id: ObjectId<Entity>) => id.Object).filter(en => nodeSet.has(en.Layer)));
|
||||||
|
else
|
||||||
|
ens.push(...app.Database.LayoutSpace.Entitys.filter(viewPoint => nodeSet.has(viewPoint.Layer) && viewPoint.IsVisible));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const isNormalLight = (en: Entity) => en instanceof AmbientLight || en instanceof DirectionalLight || en instanceof HemisphereLight;
|
||||||
|
ens.push(...app.Database.ModelSpace.Entitys.filter(en => nodeSet.has(en.Layer) && en.IsVisible));
|
||||||
|
ens.push(...app.Database.Lights.Entitys.filter(en => !isNormalLight(en) && nodeSet.has(en.Layer) && en.IsVisible));
|
||||||
|
}
|
||||||
|
app.Editor.SetSelection(ens);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 选中视口时更新图层状态 */
|
||||||
|
export const UpdateLayerByViewPoint = (viewPoint: ViewportEntity) =>
|
||||||
|
{
|
||||||
|
const layerStore = LayerStore.GetInstance();
|
||||||
|
layerStore.isShowViewportOff = true;
|
||||||
|
const UpdateNode = (nodes: ILayerNode[], Callback: (node: ILayerNode) => void, Predicate = (node: ILayerNode) => true) =>
|
||||||
|
{
|
||||||
|
nodes.map(node =>
|
||||||
|
{
|
||||||
|
if (Predicate(node))
|
||||||
|
Callback(node);
|
||||||
|
if (node.children && node.children.length > 0)
|
||||||
|
UpdateNode(node.children, Callback, Predicate);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
UpdateNode(layerStore.data, (data) =>
|
||||||
|
{
|
||||||
|
const layerTable = app.Database.LayerTable;
|
||||||
|
if (!layerTable.Has(data.name))
|
||||||
|
return;
|
||||||
|
const layer = layerTable.GetAt(data.name) as LayerTableRecord;
|
||||||
|
data.isViewportOff = viewPoint.HasFreezeLayer(layer.Id);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消视口时更新图层状态 */
|
||||||
|
export const UpdateLayerByNoViewPoint = () =>
|
||||||
|
{
|
||||||
|
const layerStore = LayerStore.GetInstance();
|
||||||
|
layerStore.isShowViewportOff = false;
|
||||||
|
};
|
@ -0,0 +1,74 @@
|
|||||||
|
/* 搜索框 */
|
||||||
|
.layer-search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 操作栏 */
|
||||||
|
.layer-operation {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-operation-btn {
|
||||||
|
margin: 0 5px;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图层列表-表头 */
|
||||||
|
.layer-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-header-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 100%;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图层列表-表项 */
|
||||||
|
.layer-body {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-body-content {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 100px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-body-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
background: rgba(100, 150, 200, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图层列表 */
|
||||||
|
.layer-list {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-list-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/* 图层特性 */
|
||||||
|
.layer-feature {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding-right: 20px;
|
||||||
|
height: 70px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-feature-current {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-feature-logo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-feature-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-feature-btn:hover {
|
||||||
|
background: rgba(200, 210, 220, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 特性匹配 */
|
||||||
|
.feature-match {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
height: 70px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-match-logo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-match-color {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 20px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -0,0 +1,360 @@
|
|||||||
|
import { Icon, Intent } from "@blueprintjs/core";
|
||||||
|
import { action, observable } from "mobx";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import * as React from 'react';
|
||||||
|
import { app } from "../../../../ApplicationServices/Application";
|
||||||
|
import { HostApplicationServices } from "../../../../ApplicationServices/HostApplicationServices";
|
||||||
|
import { Singleton } from "../../../../Common/Singleton";
|
||||||
|
import { CommandWrap } from "../../../../Editor/CommandMachine";
|
||||||
|
import { AppToaster } from "../../Toaster";
|
||||||
|
import { PropertiesStore } from "../PropertiesStore";
|
||||||
|
import { ColorBlock, ColorDialog } from "./Component/Color";
|
||||||
|
import { ColorAPI } from "./Component/ColorAPI";
|
||||||
|
import { IconSVG } from "./Component/Icon";
|
||||||
|
import { ISelectOption, SelectInLayer, TSelectValue } from "./Component/Select";
|
||||||
|
import { LayerCMD } from "./LayerCMD";
|
||||||
|
import "./LayerPanel.css";
|
||||||
|
import { LayerAction, TreeAction } from "./State/Action";
|
||||||
|
import { LayerPropertieStore, LayerStore } from "./State/Store";
|
||||||
|
import type { ILayerNode } from "./State/Type";
|
||||||
|
|
||||||
|
/** 图层状态机 */
|
||||||
|
const layerStore = LayerStore.GetInstance();
|
||||||
|
const layerAction = new LayerAction(layerStore);
|
||||||
|
|
||||||
|
interface IFeatureMatchOption
|
||||||
|
{
|
||||||
|
colorIndex?: number;
|
||||||
|
name: string;
|
||||||
|
value?: number;
|
||||||
|
onClick?: (currentItem?: ISelectOption, HandleChange?: (currentItem?: ISelectOption) => void) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LayerTopStore extends Singleton
|
||||||
|
{
|
||||||
|
/** 当前图层key */
|
||||||
|
@observable
|
||||||
|
currentLayerValue = layerStore.currentLayer.name;
|
||||||
|
|
||||||
|
/** 颜色key */
|
||||||
|
@observable
|
||||||
|
colorValue: TSelectValue = 7;
|
||||||
|
|
||||||
|
/** 默认颜色key */
|
||||||
|
@observable
|
||||||
|
normalColorValue: TSelectValue = 7;
|
||||||
|
|
||||||
|
/** 是否使用默认颜色 */
|
||||||
|
@observable
|
||||||
|
isUseNormal = false;
|
||||||
|
|
||||||
|
/** 特性匹配里的颜色选项 */
|
||||||
|
@observable
|
||||||
|
featureMatchOptions: IFeatureMatchOption[] = [
|
||||||
|
{ colorIndex: layerStore.currentLayer.colorIndex, name: "跟随图层", value: 0 },
|
||||||
|
{ colorIndex: 1, name: "红色", value: 1 },
|
||||||
|
{ colorIndex: 2, name: "黄色", value: 2 },
|
||||||
|
{ colorIndex: 3, name: "绿色", value: 3 },
|
||||||
|
{ colorIndex: 4, name: "青色", value: 4 },
|
||||||
|
{ colorIndex: 5, name: "蓝色", value: 5 },
|
||||||
|
{ colorIndex: 6, name: "紫色", value: 6 },
|
||||||
|
{ colorIndex: 7, name: "白色", value: 7 },
|
||||||
|
{ colorIndex: 8, name: "更多颜色", value: 8, onClick: this.OpenMoreColor },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 点击更多颜色 */
|
||||||
|
OpenMoreColor(currentItem: ISelectOption, HandleChange: Function)
|
||||||
|
{
|
||||||
|
app.Editor.ModalManage.RenderModal(ColorDialog, {
|
||||||
|
colorIndex: layerTopStore.featureMatchOptions[8].colorIndex,
|
||||||
|
onConfirm: (colorIndex: number) =>
|
||||||
|
{
|
||||||
|
layerTopStore.featureMatchOptions[8].colorIndex = colorIndex;
|
||||||
|
currentItem.data.colorIndex = colorIndex;
|
||||||
|
const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList;
|
||||||
|
// 没有选中实体,设置默认颜色
|
||||||
|
if (ens.length === 0)
|
||||||
|
{
|
||||||
|
HostApplicationServices.CurrentColorindex = colorIndex;
|
||||||
|
layerTopStore.normalColorValue = colorIndex;
|
||||||
|
layerTopStore.isUseNormal = true;
|
||||||
|
}
|
||||||
|
// 选中实体,设置实体颜色
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ens.forEach(en => en.ColorIndex = colorIndex);
|
||||||
|
layerTopStore.setColorValue(colorIndex);
|
||||||
|
layerTopStore.isUseNormal = false;
|
||||||
|
}, "设置颜色");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setColorValue(value: TSelectValue)
|
||||||
|
{
|
||||||
|
this.colorValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setIsUseNormal(value: boolean)
|
||||||
|
{
|
||||||
|
this.isUseNormal = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setColorIndex(colorIndex: number, index = 8)
|
||||||
|
{
|
||||||
|
this.featureMatchOptions[index].colorIndex = colorIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setCurrentLayerValue(value: string)
|
||||||
|
{
|
||||||
|
this.currentLayerValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 颜色状态机 */
|
||||||
|
const layerTopStore = LayerTopStore.GetInstance();
|
||||||
|
|
||||||
|
/** 图层特性面板 */
|
||||||
|
@observer
|
||||||
|
export class LayerPanel extends React.Component<{}, {}>
|
||||||
|
{
|
||||||
|
constructor(props: {})
|
||||||
|
{
|
||||||
|
super(props);
|
||||||
|
LayerPropertieStore.isShow = true;
|
||||||
|
}
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
const propertiesStore = PropertiesStore.GetInstance();
|
||||||
|
/** 图层颜色 */
|
||||||
|
let layerColorIndex = layerStore.currentLayer.colorIndex;
|
||||||
|
const ens = propertiesStore.GetEntitys();
|
||||||
|
const en = ens[0];
|
||||||
|
// 获取到正确的颜色
|
||||||
|
let colorIndex = 0;
|
||||||
|
const colorSet = new Set<number>();
|
||||||
|
for (const en of ens)
|
||||||
|
colorSet.add(en.ColorIndex);
|
||||||
|
if (colorSet.size > 1)
|
||||||
|
colorIndex = 0;
|
||||||
|
else if (colorSet.size === 1)
|
||||||
|
for (const color of colorSet)
|
||||||
|
colorIndex = color;
|
||||||
|
/** 是否为多种颜色 */
|
||||||
|
const isMoreColor = colorIndex === 0;
|
||||||
|
// 获取实体的图层
|
||||||
|
const currentSet: Set<string> = new Set();
|
||||||
|
ens.forEach(en => currentSet.add(en.Layer.Object.Name));
|
||||||
|
if (currentSet.size > 1)
|
||||||
|
layerTopStore.setCurrentLayerValue("多种");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (en)
|
||||||
|
{
|
||||||
|
const data = layerAction.FindNodeByName(en.Layer.Object.Name);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
layerColorIndex = data.colorIndex;
|
||||||
|
layerTopStore.setCurrentLayerValue(data.name);
|
||||||
|
colorIndex = en.ColorIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
layerTopStore.setCurrentLayerValue(layerStore.currentLayer.name);
|
||||||
|
}
|
||||||
|
// 获取实体的颜色
|
||||||
|
if (en)
|
||||||
|
{
|
||||||
|
layerTopStore.setIsUseNormal(false);
|
||||||
|
if (isMoreColor)
|
||||||
|
layerTopStore.setColorValue("多种");
|
||||||
|
else if (colorIndex === 256)
|
||||||
|
{
|
||||||
|
if (layerTopStore.colorValue !== 0)
|
||||||
|
layerTopStore.setColorValue(0);
|
||||||
|
layerTopStore.setColorIndex(layerColorIndex, 0);
|
||||||
|
}
|
||||||
|
else if (colorIndex < 8)
|
||||||
|
{
|
||||||
|
if (layerTopStore.colorValue !== colorIndex)
|
||||||
|
layerTopStore.setColorValue(colorIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (layerTopStore.colorValue !== colorIndex)
|
||||||
|
{
|
||||||
|
layerTopStore.setColorValue(colorIndex);
|
||||||
|
layerTopStore.setColorIndex(colorIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
layerTopStore.setIsUseNormal(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tool-block" >
|
||||||
|
{/* 图层特性 */}
|
||||||
|
<LayerFeature />
|
||||||
|
{/* 特性匹配 */}
|
||||||
|
<FeatureMatch />
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取图层选项(一维展开) */
|
||||||
|
export const getLayerOptions = (layerDatas: ILayerNode[]) => TreeAction.FindFlatNodes(layerDatas, (node: ILayerNode) => !node.children).map((data: ILayerNode) =>
|
||||||
|
({
|
||||||
|
label: (<>
|
||||||
|
<div style={{ width: "30px", height: "100%", display: "flex", justifyContent: "center", alignItems: "center", cursor: "pointer" }}>
|
||||||
|
{data.isOff ? <Icon icon="eye-off" size={20} /> : <Icon icon="eye-open" size={20} />}
|
||||||
|
</div>
|
||||||
|
<div style={{ width: "30px", height: "100%", display: "flex", justifyContent: "center", alignItems: "center", cursor: "pointer" }}>
|
||||||
|
{data.isLock ? <Icon icon="lock" size={20} /> : <Icon icon="unlock" size={20} />}
|
||||||
|
</div>
|
||||||
|
<div style={{ width: "15px", height: "15px", border: "1px solid #000", marginRight: "5px", background: ColorAPI.GetColor(data.colorIndex) }}></div>
|
||||||
|
<div title={data.name} style={{ flex: 1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{data.name}</div>
|
||||||
|
</>),
|
||||||
|
value: data.name
|
||||||
|
}));
|
||||||
|
|
||||||
|
/** 图层特性 */
|
||||||
|
@observer
|
||||||
|
class LayerFeature extends React.Component<{}>
|
||||||
|
{
|
||||||
|
/** 创建当前图层的选择器 */
|
||||||
|
private CreateLayerSelect = (layerDatas: ILayerNode[]) =>
|
||||||
|
{
|
||||||
|
const layerFeatureOptions = getLayerOptions(layerDatas);
|
||||||
|
return (
|
||||||
|
<div className="layer-feature-current">
|
||||||
|
<div style={{ marginRight: "10px" }}>当前图层</div>
|
||||||
|
<SelectInLayer style={{ width: "250px" }} options={layerFeatureOptions} value={layerTopStore.currentLayerValue}
|
||||||
|
onChange={(item: ISelectOption) =>
|
||||||
|
{
|
||||||
|
const value = item.value as string;
|
||||||
|
layerTopStore.currentLayerValue = value;
|
||||||
|
const data = layerAction.FindNodeByName(value);
|
||||||
|
const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList;
|
||||||
|
if (ens.length === 0)
|
||||||
|
LayerCMD.SetCurrentLayer(data);
|
||||||
|
else
|
||||||
|
LayerCMD.PutEntitysInLayer(ens, data);
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
< div className="layer-feature">
|
||||||
|
<div className="layer-feature-logo">
|
||||||
|
<IconSVG name="图层特性" size={30} />
|
||||||
|
</div>
|
||||||
|
{this.CreateLayerSelect(layerStore.data)}
|
||||||
|
<div className="layer-feature-btn"
|
||||||
|
onClick={() =>
|
||||||
|
{
|
||||||
|
const layerAction = new LayerAction(layerStore);
|
||||||
|
const currentLayer = layerAction.FindNodeByName(layerTopStore.currentLayerValue);
|
||||||
|
if (currentLayer)
|
||||||
|
LayerCMD.UpdateLock(currentLayer, false);
|
||||||
|
}}>
|
||||||
|
<IconSVG name="解锁选定对象图层" size={30} />
|
||||||
|
<div>解锁选定对象图层</div>
|
||||||
|
</div>
|
||||||
|
<div className="layer-feature-btn"
|
||||||
|
onClick={() =>
|
||||||
|
{
|
||||||
|
const layerAction = new LayerAction(layerStore);
|
||||||
|
const currentLayer = layerAction.FindNodeByName(layerTopStore.currentLayerValue);
|
||||||
|
if (currentLayer)
|
||||||
|
LayerCMD.UpdateLock(currentLayer, true);
|
||||||
|
}}>
|
||||||
|
<IconSVG name="锁定选定对象图层" size={30} />
|
||||||
|
<div>锁定选定对象图层</div>
|
||||||
|
</div>
|
||||||
|
<div className="layer-feature-btn"
|
||||||
|
onClick={() =>
|
||||||
|
{
|
||||||
|
const en = app.Editor.SelectCtrl.SelectSet.SelectEntityList[0];
|
||||||
|
if (en)
|
||||||
|
{
|
||||||
|
const data = layerAction.FindNodeByName(en.Layer.Object.Name);
|
||||||
|
if (data)
|
||||||
|
LayerCMD.SetCurrentLayer(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppToaster.show({
|
||||||
|
message: "请先选中实体",
|
||||||
|
timeout: 2000,
|
||||||
|
intent: Intent.DANGER
|
||||||
|
}, 'openfile');
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<IconSVG name="置为当前图层" size={30} />
|
||||||
|
<div>置为当前图层</div>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 特性匹配 */
|
||||||
|
@observer
|
||||||
|
class FeatureMatch extends React.Component<{}>
|
||||||
|
{
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
const options = layerTopStore.featureMatchOptions.map(data => ({
|
||||||
|
label: (<>{data.colorIndex && <ColorBlock colorIndex={data.colorIndex} />}{data.name}</>),
|
||||||
|
value: data.value,
|
||||||
|
data: { colorIndex: data.colorIndex },
|
||||||
|
onClick: data.onClick
|
||||||
|
}));
|
||||||
|
return (
|
||||||
|
< div className="feature-match">
|
||||||
|
<div className="feature-match-logo">
|
||||||
|
<IconSVG name="特性匹配" size={30} />
|
||||||
|
<div>特性匹配</div>
|
||||||
|
</div>
|
||||||
|
<div className="feature-match-color">
|
||||||
|
<div style={{ marginRight: "10px" }}>颜色</div>
|
||||||
|
<SelectInLayer value={layerTopStore.isUseNormal ? layerTopStore.normalColorValue : layerTopStore.colorValue} options={options} isColorByValue onChange={(currentItem: ISelectOption) =>
|
||||||
|
{
|
||||||
|
const value = currentItem.value as number;
|
||||||
|
// 点击更多颜色
|
||||||
|
if (value === 8)
|
||||||
|
return;
|
||||||
|
const colorIndex = value === 0 ? 256 : currentItem.data.colorIndex as number;
|
||||||
|
const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList;
|
||||||
|
// 没选中实体,设置默认颜色
|
||||||
|
if (ens.length === 0)
|
||||||
|
{
|
||||||
|
HostApplicationServices.CurrentColorindex = colorIndex;
|
||||||
|
layerTopStore.normalColorValue = value;
|
||||||
|
layerTopStore.isUseNormal = true;
|
||||||
|
}
|
||||||
|
// 选中实体,设置实体颜色
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CommandWrap(() =>
|
||||||
|
{
|
||||||
|
ens.forEach(en => en.ColorIndex = colorIndex);
|
||||||
|
layerTopStore.setColorValue(value);
|
||||||
|
layerTopStore.isUseNormal = false;
|
||||||
|
}, "设置颜色");
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { observable } from "mobx";
|
||||||
|
import { Singleton } from "../../../../../Common/Singleton";
|
||||||
|
import type { ILayerNode } from "./Type";
|
||||||
|
|
||||||
|
/** 图层的状态单例 */
|
||||||
|
export class LayerStore extends Singleton
|
||||||
|
{
|
||||||
|
/** 自增ID */
|
||||||
|
ID = { file: 0, folder: 0 };
|
||||||
|
|
||||||
|
/** 图层数据 */
|
||||||
|
@observable
|
||||||
|
data: ILayerNode[] = [
|
||||||
|
{ name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 当前图层 */
|
||||||
|
@observable
|
||||||
|
currentLayer = this.data[0];
|
||||||
|
|
||||||
|
/** 是否显示视口冻结 */
|
||||||
|
@observable
|
||||||
|
isShowViewportOff = false;
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
Init()
|
||||||
|
{
|
||||||
|
this.data = [
|
||||||
|
{ name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false },
|
||||||
|
];
|
||||||
|
this.currentLayer = this.data[0];
|
||||||
|
this.ID = { file: 0, folder: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 图层特性 */
|
||||||
|
export const LayerPropertieStore = {
|
||||||
|
/** 是否显示 */
|
||||||
|
isShow: false
|
||||||
|
};
|
@ -0,0 +1,35 @@
|
|||||||
|
/** 树的基本数据类型 */
|
||||||
|
export interface INode
|
||||||
|
{
|
||||||
|
/** 名称 */
|
||||||
|
name: string;
|
||||||
|
/** 子节点 */
|
||||||
|
children?: INode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 图层的数据类型 */
|
||||||
|
export interface ILayerNode extends INode
|
||||||
|
{
|
||||||
|
children?: ILayerNode[];
|
||||||
|
/** 是否为当前图层 */
|
||||||
|
isCurrent?: boolean;
|
||||||
|
/** 是否隐藏 */
|
||||||
|
isOff: boolean;
|
||||||
|
/** 是否锁定 */
|
||||||
|
isLock: boolean;
|
||||||
|
/** 是否视口隐藏(仅在视口模式下有效) */
|
||||||
|
isViewportOff?: boolean;
|
||||||
|
/** 图层颜色索引 */
|
||||||
|
colorIndex?: number;
|
||||||
|
|
||||||
|
/* ---- 以下仅用于UI ---- */
|
||||||
|
|
||||||
|
/** 是否显示(用于搜索过滤) */
|
||||||
|
visible: boolean;
|
||||||
|
/** 是否选中 */
|
||||||
|
selected: boolean;
|
||||||
|
/** 是否可输入(用于重命名) */
|
||||||
|
changeable: boolean;
|
||||||
|
/** 是否展开 */
|
||||||
|
expanded?: boolean;
|
||||||
|
}
|
Loading…
Reference in new issue