diff --git a/src/ApplicationServices/Application.ts b/src/ApplicationServices/Application.ts index 634ea7906..fbf9b4077 100644 --- a/src/ApplicationServices/Application.ts +++ b/src/ApplicationServices/Application.ts @@ -44,6 +44,7 @@ import { WebRtcRenderer } from '../GraphicsSystem/WebRtcRenderer'; import { IndexedDbStore } from '../IndexedDb/IndexedDbStore'; import { InitClipperCpp } from '../Nest/Common/ClipperCpp'; import { CommandReactor } from '../Reactor/CommandReactor'; +import { DeleteMaterialReactor } from '../Reactor/DeleteMaterialReactor'; import { LayerReactor } from '../Reactor/LayerReactor'; import { RelevanceCuttingReactor } from '../Reactor/RelevanceCuttingReactor'; import { SyncDataReactor } from '../Reactor/SyncDataReactor'; @@ -280,6 +281,7 @@ export class ApplicationService /** 图层反应器 */ const layerReactor = new LayerReactor(); + new DeleteMaterialReactor(); // 删除材质反应器 //在更新实体后,如果网洞被删除,则操作控制器被禁用 app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) => diff --git a/src/Common/ApplyMaterial.ts b/src/Common/ApplyMaterial.ts index bc816e900..35b23de10 100644 --- a/src/Common/ApplyMaterial.ts +++ b/src/Common/ApplyMaterial.ts @@ -243,3 +243,27 @@ function LockMtlToaster(count: number = 0, hasEntMtlLocked?: boolean, hasAllMtlL intent: Intent.WARNING, }, "partMeshMaterialMock"); } + +/** + * 获取使用指定材质的实体 + * @param {PhysicalMaterialRecord} mtl 材质 + * @param {boolean} [containErasedMtl=false] 是否包含被删除的材质 + * @return {*} {Entity[]} + */ +export function GetUseCurMtlEntities(mtl: PhysicalMaterialRecord, containErasedMtl: boolean = false): Entity[] +{ + const entities: Entity[] = []; + + for (let e of app.Database.ModelSpace.Entitys) + { + if (e.IsErase) continue; + + if (!IsMeshMaterialEntity(e)) continue; + + const allMtl = e.GetPhyMtlRecords(containErasedMtl) || []; + if (allMtl.includes(mtl)) + entities.push(e); + } + + return entities; +}; diff --git a/src/Common/CommandNames.ts b/src/Common/CommandNames.ts index e4c04e615..e510e262e 100644 --- a/src/Common/CommandNames.ts +++ b/src/Common/CommandNames.ts @@ -349,6 +349,7 @@ export enum CommandNames M0 = "M0", PackageGroupMove0 = "PACKAGEGROUPMOVE0", ApplyMtl = "APPLYMTL",//应用材质 + DeleteMtl = "DELETEMTL",//删除材质 封边属性编辑 = "封边属性编辑", 板边备注编辑 = "板边备注编辑", 排钻属性编辑 = "排钻属性编辑", diff --git a/src/DatabaseServices/Entity/CompositeEntity.ts b/src/DatabaseServices/Entity/CompositeEntity.ts index de5c231c9..7808f37ad 100644 --- a/src/DatabaseServices/Entity/CompositeEntity.ts +++ b/src/DatabaseServices/Entity/CompositeEntity.ts @@ -212,7 +212,7 @@ export abstract class CompositeEntity extends Entity }; } - GetPhyMtlRecords() + GetPhyMtlRecords(containErased: boolean = false) { const materials: PhysicalMaterialRecord[] = []; @@ -220,7 +220,7 @@ export abstract class CompositeEntity extends Entity { if (e === this) return; - const res = e.GetPhyMtlRecords(); + const res = e.GetPhyMtlRecords(containErased); if (res.length) arrayPushArray(materials, res); }); diff --git a/src/DatabaseServices/Entity/Entity.ts b/src/DatabaseServices/Entity/Entity.ts index c1424bcc3..f42048818 100644 --- a/src/DatabaseServices/Entity/Entity.ts +++ b/src/DatabaseServices/Entity/Entity.ts @@ -180,11 +180,19 @@ export class Entity extends CADObject }; } - GetPhyMtlRecords(): PhysicalMaterialRecord[] + /** + * 获取实体的 PhysicalMaterialRecord + * @param {boolean} [containErased=false] 是否包含被删除的材质 + * @return {*} {PhysicalMaterialRecord[]} + * @memberof Entity + */ + GetPhyMtlRecords(containErased: boolean = false): PhysicalMaterialRecord[] { - const mtl = this.Material; - if (mtl?.Object) - return [mtl.Object]; + if (this._MaterialId) + { + if (containErased || !this._MaterialId.IsErase) + return [this._MaterialId.Object]; + } return []; } diff --git a/src/DatabaseServices/Entity/EntityFbx.ts b/src/DatabaseServices/Entity/EntityFbx.ts index 488b2dc92..b2b7662c5 100644 --- a/src/DatabaseServices/Entity/EntityFbx.ts +++ b/src/DatabaseServices/Entity/EntityFbx.ts @@ -197,16 +197,18 @@ export class EntityFbx extends Entity }; } - private _GetValidOWMtlRecord(index: number): PhysicalMaterialRecord | undefined + private _GetValidOWMtlRecord(index: number, containErased: boolean = false): PhysicalMaterialRecord | undefined { const obj = this._OverWriteMaterial.get(index)?.Object; - if (obj && !obj.IsErase) - return obj; + if (obj) + if (containErased || !obj.IsErase) + return obj; + return undefined; } // 注意:不含默认的fbx材质record - GetPhyMtlRecords() + GetPhyMtlRecords(containErased: boolean = false) { const materials: PhysicalMaterialRecord[] = []; this.DrawObject.traverse(o => @@ -218,7 +220,7 @@ export class EntityFbx extends Entity let allUseOW = true; for (let i = 0; i < o.material.length; i++) { - const curMtl = this._GetValidOWMtlRecord(i); + const curMtl = this._GetValidOWMtlRecord(i, containErased); if (curMtl) materials.push(curMtl); else @@ -227,7 +229,7 @@ export class EntityFbx extends Entity } else { - const curMtl = this._GetValidOWMtlRecord(0); + const curMtl = this._GetValidOWMtlRecord(0, containErased); if (curMtl) materials.push(curMtl); } diff --git a/src/DatabaseServices/Entity/EntityRef.ts b/src/DatabaseServices/Entity/EntityRef.ts index 786e7f42c..b76511b43 100644 --- a/src/DatabaseServices/Entity/EntityRef.ts +++ b/src/DatabaseServices/Entity/EntityRef.ts @@ -272,15 +272,16 @@ export class EntityRef extends Entity }; } - private _GetValidOWMtlRecord(index: number): PhysicalMaterialRecord | undefined + private _GetValidOWMtlRecord(index: number, containErased: boolean = false): PhysicalMaterialRecord | undefined { const obj = this._OverWriteMaterial.get(index)?.Object; - if (obj && !obj.IsErase) - return obj; + if (obj) + if (containErased || !obj.IsErase) + return obj; return undefined; } - GetPhyMtlRecords() + GetPhyMtlRecords(containErased: boolean = false) { const materials: PhysicalMaterialRecord[] = []; this.DrawObject.traverse(o => @@ -291,14 +292,14 @@ export class EntityRef extends Entity { for (let i = 0; i < o.material.length; i++) { - const curMtl = this._GetValidOWMtlRecord(i); + const curMtl = this._GetValidOWMtlRecord(i, containErased); if (curMtl) materials.push(curMtl); } } else { - const curMtl = this._GetValidOWMtlRecord(0); + const curMtl = this._GetValidOWMtlRecord(0, containErased); if (curMtl) materials.push(curMtl); } diff --git a/src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline.ts b/src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline.ts index 7e5c08d40..c3fc88ead 100644 --- a/src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline.ts +++ b/src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline.ts @@ -595,19 +595,23 @@ export class RoomHolePolyline extends RoomHoleBase }; } - GetPhyMtlRecords() + GetPhyMtlRecords(containErased: boolean = false) { const materials: PhysicalMaterialRecord[] = []; for (const [, v] of this._OverWriteMaterial) { - if (!v?.IsErase && v?.Object) - materials.push(v.Object); + if (v?.Object) + if (!v?.IsErase || containErased) + materials.push(v?.Object); } const meshSize = this.MeshMaterial.length; - if (this._OverWriteMaterial.size !== meshSize && super.Material?.Object) - materials.push(super.Material.Object); + if (this._OverWriteMaterial.size !== meshSize && this._MaterialId?.Object) + { + if (containErased || !this._MaterialId.IsErase) + materials.push(this._MaterialId?.Object); + } return materials; } diff --git a/src/DatabaseServices/Room/Entity/Wall/RoomWallBase.ts b/src/DatabaseServices/Room/Entity/Wall/RoomWallBase.ts index 96e3cf85e..ee10f3a44 100644 --- a/src/DatabaseServices/Room/Entity/Wall/RoomWallBase.ts +++ b/src/DatabaseServices/Room/Entity/Wall/RoomWallBase.ts @@ -188,19 +188,23 @@ export abstract class RoomWallBase extends RoomBase }; } - GetPhyMtlRecords() + GetPhyMtlRecords(containErased: boolean = false) { const materials: PhysicalMaterialRecord[] = []; for (const [, v] of this.OverWriteMaterial) { - if (!v?.IsErase && v?.Object) - materials.push(v?.Object); + if (v?.Object) + if (!v?.IsErase || containErased) + materials.push(v?.Object); } const meshSize = this.MeshMaterials.length; - if (this.OverWriteMaterial.size !== meshSize && super.Material?.Object) - materials.push(super.Material.Object); + if (this.OverWriteMaterial.size !== meshSize && this._MaterialId?.Object) + { + if (containErased || !this._MaterialId.IsErase) + materials.push(this._MaterialId?.Object); + } return materials; } diff --git a/src/Reactor/DeleteMaterialReactor.ts b/src/Reactor/DeleteMaterialReactor.ts new file mode 100644 index 000000000..04bd0a656 --- /dev/null +++ b/src/Reactor/DeleteMaterialReactor.ts @@ -0,0 +1,38 @@ +import { end } from "xaop"; +import { app } from "../ApplicationServices/Application"; +import { GetUseCurMtlEntities } from "../Common/ApplyMaterial"; +import { CommandNames } from "../Common/CommandNames"; +import { UpdateDraw } from "../Common/Status"; +import { CommandHistoryRecord } from "../DatabaseServices/CommandHistoryRecord"; +import { PhysicalMaterialRecord } from "../DatabaseServices/PhysicalMaterialRecord"; + +export class DeleteMaterialReactor +{ + constructor() + { + const DeleteMtlFunction = () => + { + return (cmdName: string, historyRec: CommandHistoryRecord) => + { + if (cmdName !== CommandNames.DeleteMtl) return; + for (let [id,] of historyRec.HistoryList) + { + if (id.Object instanceof PhysicalMaterialRecord) + this.UpdateMtl(id.Object); + } + }; + }; + + const DeleteMtlUndo = DeleteMtlFunction(); + const DeleteMtlRedo = DeleteMtlFunction(); + end(app.Database.hm, app.Database.hm.RedoEvent, DeleteMtlRedo); + end(app.Database.hm, app.Database.hm.UndoEvent, DeleteMtlUndo); + } + + UpdateMtl(mtl: PhysicalMaterialRecord) + { + const entities = GetUseCurMtlEntities(mtl, true); + for (const en of entities) + en.Update(UpdateDraw.Material); + } +} diff --git a/src/UI/Components/Asset.tsx b/src/UI/Components/Asset.tsx index bc8724847..3224a8b72 100644 --- a/src/UI/Components/Asset.tsx +++ b/src/UI/Components/Asset.tsx @@ -4,7 +4,8 @@ import { observer } from 'mobx-react'; import React, { CSSProperties, DragEvent } from 'react'; import { end } from 'xaop'; import { app } from '../../ApplicationServices/Application'; -import { ApplyMtlToSelectEntityListCmd } from '../../Common/ApplyMaterial'; +import { ApplyMtlToSelectEntityListCmd, GetUseCurMtlEntities } from '../../Common/ApplyMaterial'; +import { CommandNames } from '../../Common/CommandNames'; import { ImgsUrl, MaterialUrls } from '../../Common/HostUrl'; import { IsMeshMaterialEntity } from '../../Common/IsMeshMaterialEntity'; import { Post, PostJson, RequestStatus } from '../../Common/Request'; @@ -13,7 +14,6 @@ import { Sleep } from '../../Common/Sleep'; import { UpdateDraw } from '../../Common/Status'; import { Intent } from '../../Common/Toaster'; import { Board } from '../../DatabaseServices/Entity/Board'; -import { Entity } from '../../DatabaseServices/Entity/Entity'; import { PhysicalMaterialRecord } from '../../DatabaseServices/PhysicalMaterialRecord'; import { TextureTableRecord } from '../../DatabaseServices/Texture'; import { CommandWrap, commandMachine } from '../../Editor/CommandMachine'; @@ -188,7 +188,7 @@ export class Asset extends React.Component _HighLightEntity = () => { - let ents = this._GetUseCurMtlEntitys(); + let ents = GetUseCurMtlEntities(this.props.material); app.Editor.SetSelection(ents); AppToaster.show({ message: `有${ents.length}个实体使用了该材质!`, @@ -200,7 +200,7 @@ export class Asset extends React.Component //将使用当前材质的板引用板材信息 _ApplyUseCurBrsGoodInfo = async () => { - let ents = this._GetUseCurMtlEntitys(); + let ents = GetUseCurMtlEntities(this.props.material); let brs = ents.filter(e => e instanceof Board) as Board[]; if (brs.length === 0) { @@ -322,33 +322,11 @@ export class Asset extends React.Component CommandWrap(() => { - let allEnt = this._GetUseCurMtlEntitys(); + let allEnt = GetUseCurMtlEntities(this.props.material); app.Database.MaterialTable.Remove(this.props.material as PhysicalMaterialRecord); for (let en of allEnt) en.Update(UpdateDraw.Material); - }, "删除材质"); - }; - - /** - * 获得使用当前材质的实体列表 (板和五金) - */ - _GetUseCurMtlEntitys() - { - const ents: Entity[] = []; - - const mtl = this.props.material; - for (let e of app.Database.ModelSpace.Entitys) - { - if (e.IsErase) continue; - - if (!IsMeshMaterialEntity(e)) continue; - - const allMtl = e.GetPhyMtlRecords() || []; - if (allMtl.includes(mtl)) - ents.push(e); - } - - return ents; + }, CommandNames.DeleteMtl); }; _HandleStart = (e: DragEvent) =>