!2389 功能:在用材质栏,增加锁定/解锁功能

pull/2919/MERGE
黄诗津 2 months ago committed by ChenX
parent cb0977cc12
commit b5a611ff0c

@ -136,8 +136,9 @@ export class Entity extends CADObject
GetMaterialSlots() { }
SetMaterialAtSlot(mtl: ObjectId, slotIndex: number)
SetMaterialAtSlot(mtl: ObjectId, slotIndex?: number)
{
if ((this.Material?.Object as PhysicalMaterialRecord)?.IsMaterialLock) return;
this.Material = mtl;
}
@ -173,6 +174,10 @@ export class Entity extends CADObject
this.UpdateDrawObjectMaterial(type, obj);
}
}
SetAllMaterialAtSlot(mtl: ObjectId)
{
this.SetMaterialAtSlot(mtl);
}
set ColorIndex(color: number)
{

@ -180,6 +180,9 @@ export class EntityRef extends Entity
SetMaterialAtSlot(mtl: ObjectId<PhysicalMaterialRecord>, slotIndex: number)
{
let curMtl = this._OverWriteMaterial.get(slotIndex);
if (curMtl && (curMtl.Object as PhysicalMaterialRecord).IsMaterialLock) return;
if (this._OverWriteMaterial.get(slotIndex) !== mtl)
{
this.WriteAllObjectRecord();
@ -188,6 +191,33 @@ export class EntityRef extends Entity
}
}
SetAllMaterialAtSlot(mtl: ObjectId<PhysicalMaterialRecord>)
{
this.DrawObject.traverse(o =>
{
if (o instanceof Mesh)
{
if (Array.isArray(o.material))
{
for (let i = 0; i < o.material.length; i++)
{
let curMtl = this._OverWriteMaterial.get(i);
if (curMtl && (curMtl.Object as PhysicalMaterialRecord).IsMaterialLock) continue;
this.WriteAllObjectRecord();
this._OverWriteMaterial.set(i, mtl);
}
}
else
{
this.WriteAllObjectRecord();
this._OverWriteMaterial.set(0, mtl);
}
}
});
this.Update(UpdateDraw.Material);
}
//del_exp_start
async FetchBox()
{

@ -101,6 +101,8 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
color: "",
material: "",
};
private _isMaterialLock: boolean = false;//材质锁
private material = new MeshPhysicalMaterial({});
constructor()
@ -116,6 +118,12 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
}
async Update()
{
await this.PhysicalMaterialUpdate();
}
//因为Asset.tsx监听了Update的事件,然后又要去调用这个,导致重复监听,所以分离出这个函数
async PhysicalMaterialUpdate()
{
this.material[USE_WORLD_UV] = this.UseWorldUV;
if (this.material[USE_WORLD_UV])
@ -234,6 +242,17 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
this.WriteAllObjectRecord();
Object.assign(this._goodsInfo, info);
}
get IsMaterialLock()
{
return this._isMaterialLock;
}
set IsMaterialLock(v)
{
if (this._isMaterialLock === v) return;
this.WriteAllObjectRecord();
this._isMaterialLock = v;
}
//#region -------------------------File-------------------------
ReadFile(file: CADFiler)
{
@ -322,6 +341,10 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
this.refraction = file.Read();
this.side = file.Read();
}
if (ver > 10)
{
this._isMaterialLock = file.Read();
}
}
this.Update();
@ -330,7 +353,7 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
WriteFile(file: CADFiler)
{
super.WriteFile(file);
file.Write(10);
file.Write(11);
file.Write(this.color);
file.Write(this.transparent);
file.Write(this.matalness);
@ -402,6 +425,9 @@ export class PhysicalMaterialRecord extends MaterialTableRecord
//ver10
file.Write(this.refraction);
file.Write(this.side);
//ver11
file.Write(this.IsMaterialLock);
}
//#endregion
}

@ -511,6 +511,9 @@ export class RoomHolePolyline extends RoomHoleBase
SetMaterialAtSlot(mtl: ObjectId<PhysicalMaterialRecord>, slotIndex: number)
{
let curMtl = this._OverWriteMaterial.get(slotIndex);
if ((curMtl.Object as PhysicalMaterialRecord).IsMaterialLock) return;
if (this._OverWriteMaterial.get(slotIndex) !== mtl)
{
this.WriteAllObjectRecord();
@ -519,6 +522,33 @@ export class RoomHolePolyline extends RoomHoleBase
}
}
SetAllMaterialAtSlot(mtl: ObjectId<PhysicalMaterialRecord>)
{
this.DrawObject.traverse(o =>
{
if (o instanceof Mesh)
{
if (Array.isArray(o.material))
{
for (let i = 0; i < o.material.length; i++)
{
let curMtl = this._OverWriteMaterial.get(i);
if (curMtl && (curMtl.Object as PhysicalMaterialRecord).IsMaterialLock) continue;
this.WriteAllObjectRecord();
this._OverWriteMaterial.set(i, mtl);
}
}
else
{
this.WriteAllObjectRecord();
this._OverWriteMaterial.set(0, mtl);
}
}
});
this.Update(UpdateDraw.Material);
}
protected get MeshMaterial(): Material[]
{
let defaultMtl: Material;

@ -7,6 +7,20 @@ import { Factory } from './CADFactory';
import { CADFiler } from './CADFiler';
import { SymbolTableRecord } from './SymbolTableRecord';
export class TextureTableEventBus
{
private static _SingleInstance: TextureTableEventBus;
static GetInstance(): TextureTableEventBus
{
if (this._SingleInstance) return this._SingleInstance;
this._SingleInstance = new TextureTableEventBus;
return this._SingleInstance;
}
UpdateEvent(texture: TextureTableRecord)
{
}
}
/**
* ..
*/
@ -50,6 +64,14 @@ export class TextureTableRecord extends SymbolTableRecord
async Update()
{
//del_exp_start
await this.TextureUpdate();
TextureTableEventBus.GetInstance().UpdateEvent(this);
//del_exp_end return "";
}
//del_exp_start
async TextureUpdate()
{
if (this.imageUrl.endsWith("Default.png") || !this.imageUrl)
{
this.imgUrl = ResourcesCDN_HOST + "Default.webp";
@ -79,8 +101,8 @@ export class TextureTableRecord extends SymbolTableRecord
this.AsyncUpdated();
return this.imgUrl;
//del_exp_end return "";
}
//del_exp_end
private waits: Function[] = [];
async WaitUpdate()

@ -1,4 +1,5 @@
import { ContextMenu, Menu, MenuItem } from '@blueprintjs/core';
import { ContextMenu, Icon, Menu, MenuItem } from '@blueprintjs/core';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import React, { CSSProperties, DragEvent } from 'react';
import { end } from 'xaop';
@ -8,6 +9,7 @@ import { ImgsUrl, MaterialUrls } from '../../Common/HostUrl';
import { IsMeshMaterialEntity } from '../../Common/IsMeshMaterialEntity';
import { Post, PostJson, RequestStatus } from '../../Common/Request';
import { MaterialOut, deflate } from '../../Common/SerializeMaterial';
import { Sleep } from '../../Common/Sleep';
import { Intent } from '../../Common/Toaster';
import { Hole } from '../../DatabaseServices/3DSolid/Hole';
import { Board } from '../../DatabaseServices/Entity/Board';
@ -26,6 +28,7 @@ import { ICON_CDN, IconEnum } from '../IconEnum';
import { appUi } from '../Layout/ApplicationLayout';
import { ApplyGoodInfo } from './ApplyGoodInfo';
import { AppConfirm } from './Common/Confirm';
import { EDITMATERIAL, MATERIALLOCK } from './MaterialExplorer';
import { AppToaster } from './Toaster';
//蓝图.
@ -39,6 +42,7 @@ const RootStyle: CSSProperties = {
justifyContent: "space-between",
alignItems: "center",
paddingTop: "10px",
position: "relative",
};
//材质球上方的图片预览
@ -60,6 +64,7 @@ const TextStyle: CSSProperties = {
textOverflow: "ellipsis",
whiteSpace: "nowrap",
height: "20px",
padding: "0 10px",
width: "100%",
};
@ -84,6 +89,7 @@ export enum CurDefMtlType
@observer
export class Asset extends React.Component<AssetProps, {}>
{
@observable isLock = this.props.material.objectId.Object.IsMaterialLock;
_Image = React.createRef<HTMLImageElement>();
_DivColorRef = React.createRef<HTMLDivElement>();
_CurWallMtlIconMarginBottom: number = 2;
@ -96,7 +102,11 @@ export class Asset extends React.Component<AssetProps, {}>
componentDidMount()
{
this._RemoveCall.push(end(this.props.material, this.props.material.Update, () => { this._UpdateRenderPreview(); }));
this._RemoveCall.push(end(this.props.material, this.props.material.Update, () =>
{
this._UpdateRenderPreview();
this.isLock = this.props.material.IsMaterialLock;
}));
this._UpdateRenderPreview();
}
@ -105,6 +115,14 @@ export class Asset extends React.Component<AssetProps, {}>
this._Destroy();
}
updateTexture = (texture: TextureTableRecord) =>
{
if (this.props.material.map?.Object === texture)
{
this._UpdateRenderPreview();
}
};
/**
*
*/
@ -112,11 +130,11 @@ export class Asset extends React.Component<AssetProps, {}>
{
if (this._RenderIng) return;
this._RenderIng = true;
await Sleep(20); //减少更新频率
let material = this.props.material;
if (material.useMap && material.map && material.map.Object)
await (material.map.Object as TextureTableRecord).Update();
await material.Update();
await (material.map.Object as TextureTableRecord).TextureUpdate();
await material.PhysicalMaterialUpdate();
let imgUrl = MaterialRendererSingle().render(material.Material);
@ -133,7 +151,7 @@ export class Asset extends React.Component<AssetProps, {}>
if (this._DivColorRef.current)
{
if (!material.map)
if (!(material.useMap && material.map))
this._DivColorRef.current.style.border = "1px solid black";
else
this._DivColorRef.current.style.border = "none";
@ -154,7 +172,7 @@ export class Asset extends React.Component<AssetProps, {}>
_HandleDoubleClick = async () =>
{
await app.Editor.ModalManage.EndExecingCmd();
if (!commandMachine.CommandStart("编辑材质"))
if (!commandMachine.CommandStart(EDITMATERIAL))
{
AppToaster.show({
message: "命令正在执行中,无法开始编辑材质!",
@ -190,10 +208,13 @@ export class Asset extends React.Component<AssetProps, {}>
en.OverWriteMaterial.set(num, material.Id);
}
en.Material = material.Id;
if (en instanceof BulkheadCeiling)
{
en.Material = material.Id;
en.SetDefaultMaterialAtAllSlot();
}
else if (IsMeshMaterialEntity(en))
en.SetAllMaterialAtSlot(material.Id);
if (en instanceof Board)
{
@ -420,6 +441,7 @@ export class Asset extends React.Component<AssetProps, {}>
render()
{
const { material } = this.props;
//样式
let style: React.CSSProperties = { ...RootStyle };
if (!userConfig.isLargeIcon)//大图标
@ -502,6 +524,21 @@ export class Asset extends React.Component<AssetProps, {}>
>
<span>{this.props.material.Name}</span>
</div>
<div
className={this.isLock ? 'material-lock' : 'material-unlock'}
onClick={(e) =>
{
e.stopPropagation();
this.isLock = !this.isLock;
CommandWrap(() =>
{
material.objectId.Object.IsMaterialLock = !material.objectId.Object.IsMaterialLock;
}, MATERIALLOCK);
}}
onDoubleClick={(e) => { e.stopPropagation(); }}
>
<Icon size={12} icon={this.isLock ? "lock" : "unlock"}></Icon>
</div>
</div>
);
}

@ -130,6 +130,24 @@
}
}
}
.material-lock ,
.material-unlock{
position: absolute;
right: 0;
bottom: 3px;
padding: 0 2px;
cursor: pointer;
}
.material-unlock {
opacity: 0;
}
.material-unlock:hover {
background-color: #cccccc78;
opacity: 1;
}
}
}

@ -15,6 +15,7 @@ import { PhysicalMaterialRecord } from '../../DatabaseServices/PhysicalMaterialR
import { BulkheadCeiling } from '../../DatabaseServices/Room/Entity/Ceiling/BulkheadCeiling';
import { MaterialTable } from '../../DatabaseServices/Tables/MaterialTable';
import { Text } from '../../DatabaseServices/Text/Text';
import { TextureTableEventBus, TextureTableRecord } from '../../DatabaseServices/Texture';
import { CommandWrap } from '../../Editor/CommandMachine';
import { GenerateRaycaster, PointPick, Raycast } from '../../Editor/PointPick';
import { SelectSetBase } from '../../Editor/SelectBase';
@ -43,6 +44,9 @@ const rootStyle: React.CSSProperties = {
border: "1px solid #ccc",
};
export const MATERIALLOCK = "材质锁";
export const EDITMATERIAL = "编辑材质";
/**
*
* 使:
@ -52,57 +56,69 @@ const rootStyle: React.CSSProperties = {
export class MaterialExplorer extends React.Component<{ materialTable: MaterialTable; }, {}>
{
private _MaterialListPanelRef = React.createRef<HTMLDivElement>();
AssetRefs = [...this.props.materialTable.Materials.entries()].map(() =>
{
return React.createRef<Asset>();
});
@observable private _selectMtls = new Set<PhysicalMaterialRecord>();
private _RemoveFunc: Function;
private _RemoveFunc: Function[] = [];
constructor(p, s)
{
super(p, s);
this._RemoveFunc = end(app.Editor.SelectCtrl, app.Editor.SelectCtrl.AddSelect, (ss: SelectSetBase) =>
{
if (!userConfig.isHighlightMaterial)
{
if (this._selectMtls.size) this._selectMtls.clear();
return;
};
runInAction(() =>
this._RemoveFunc.push(
//当选中物体时 亮显右侧面板的材质
end(app.Editor.SelectCtrl, app.Editor.SelectCtrl.AddSelect, (ss: SelectSetBase) =>
{
this._selectMtls.clear();
if (!userConfig.isHighlightMaterial)
{
if (this._selectMtls.size) this._selectMtls.clear();
return;
};
for (let en of app.Editor.SelectCtrl.SelectSet.SelectEntityList)
runInAction(() =>
{
if (en instanceof Curve) continue;
if (en instanceof VisualSpaceBox) continue;
if (en instanceof Text) continue;
if (en instanceof Hole) continue;
this._selectMtls.clear();
let mtl = (en.Material?.Object as PhysicalMaterialRecord) ?? app.Database.DefaultMaterial;
for (let en of app.Editor.SelectCtrl.SelectSet.SelectEntityList)
{
if (en instanceof Curve) continue;
if (en instanceof VisualSpaceBox) continue;
if (en instanceof Text) continue;
if (en instanceof Hole) continue;
this._selectMtls.add(mtl);
}
});
let mtl = (en.Material?.Object as PhysicalMaterialRecord) ?? app.Database.DefaultMaterial;
let panelEl = this._MaterialListPanelRef.current;
if (panelEl)
{
let index = 0;
for (let mtl of this._selectMtls)
this._selectMtls.add(mtl);
}
});
let panelEl = this._MaterialListPanelRef.current;
if (panelEl)
{
for (let [, omtl] of app.Database.MaterialTable.Materials)
let index = 0;
for (let mtl of this._selectMtls)
{
if (omtl === mtl) break;
index++;
for (let [, omtl] of app.Database.MaterialTable.Materials)
{
if (omtl === mtl) break;
index++;
}
break;
}
break;
}
if (userConfig.isLargeIcon)
panelEl.scrollTop = Math.floor(index / 2) * 120;
else
panelEl.scrollTop = Math.floor(index / 3) * 90;
}
});
if (userConfig.isLargeIcon)
panelEl.scrollTop = Math.floor(index / 2) * 120;
else
panelEl.scrollTop = Math.floor(index / 3) * 90;
}
}),
//更新材质贴图
end(TextureTableEventBus.GetInstance(), TextureTableEventBus.GetInstance().UpdateEvent, (texture: TextureTableRecord) =>
{
this.AssetRefs.forEach(ass => { ass.current.updateTexture(texture); });
})
);
}
componentDidMount()
@ -113,9 +129,18 @@ export class MaterialExplorer extends React.Component<{ materialTable: MaterialT
componentWillUnmount()
{
document.body.removeEventListener("drop", this.handleDrop);
this._RemoveFunc();
document.removeEventListener("drop", this.handleDrop);
this._RemoveFunc.forEach(f => f());
this._RemoveFunc.length = 0;
}
updateAssetRef = () =>
{
this.AssetRefs = [...this.props.materialTable.Materials.values()].map(() =>
{
return React.createRef<Asset>();
});
};
handleDrop = async (e: DragEvent) =>
{
let material = app.Database.MaterialTable.GetAt(e.dataTransfer.getData("mat"));
@ -144,7 +169,7 @@ export class MaterialExplorer extends React.Component<{ materialTable: MaterialT
if (userConfig.isModifyMaterial)
ApplyGoodInfo(en, material);
}
}, "拽拖材质应用");
}, "拽拖材质应用");
return;
}
@ -158,6 +183,9 @@ export class MaterialExplorer extends React.Component<{ materialTable: MaterialT
for (let o of selectObj)
{
let en = GetEntity(o);
if ((en.Material?.Object as PhysicalMaterialRecord)?.IsMaterialLock) continue;
if (IsMeshMaterialEntity(en))
en.Material = material.Id;
@ -185,6 +213,7 @@ export class MaterialExplorer extends React.Component<{ materialTable: MaterialT
};
render()
{
this.updateAssetRef();
return (
<div className='material-explorer'>
<div className='material-config'>
@ -242,10 +271,11 @@ export class MaterialExplorer extends React.Component<{ materialTable: MaterialT
}}
>
{
[...this.props.materialTable.Materials.values()].map((material) =>
[...this.props.materialTable.Materials.values()].map((material, i) =>
{
return (
<Asset
ref={this.AssetRefs[i]}
key={material.Material.uuid}
material={material}
hightLight={this._selectMtls.has(material)}

@ -138,6 +138,7 @@ export class MaterialList extends React.Component<IImgListProps, {}>
{
let obj = intersection.object;
let en = GetEntity(obj);
if (IsMeshMaterialEntity(en))
en.SetMaterialAtSlot(mtl.Id, intersection.face.materialIndex);
@ -153,6 +154,9 @@ export class MaterialList extends React.Component<IImgListProps, {}>
for (let o of selectObj)
{
let en = GetEntity(o);
if ((en.Material?.Object as PhysicalMaterialRecord)?.IsMaterialLock) continue;
if (IsMeshMaterialEntity(en))
en.Material = mtl.Id;
if (en instanceof Board)
@ -278,10 +282,13 @@ export class MaterialList extends React.Component<IImgListProps, {}>
en.OverWriteMaterial.set(num, newMaterial.Id);
}
en.Material = newMaterial.Id;
if (en instanceof BulkheadCeiling)
{
en.Material = newMaterial.Id;
en.SetDefaultMaterialAtAllSlot();
}
else if (IsMeshMaterialEntity(en))
en.SetAllMaterialAtSlot(newMaterial.Id);
if (en instanceof Board)
{

@ -503,10 +503,13 @@ export class ResourceItem extends Component<{ module: ModuleData; icon?: IconNam
en.OverWriteMaterial.set(num, material.Id);
}
en.Material = material.Id;
if (en instanceof BulkheadCeiling)
{
en.Material = material.Id;
en.SetDefaultMaterialAtAllSlot();
}
else
en.SetAllMaterialAtSlot(material.Id);
if (en instanceof Board)
{

@ -788,6 +788,8 @@ export default class ResourceStore
for (let o of selectObj)
{
let en = GetEntity(o);
if ((en.Material?.Object as PhysicalMaterialRecord)?.IsMaterialLock) continue;
if (IsMeshMaterialEntity(en))
en.Material = material.Id;

@ -139,10 +139,14 @@ export default class UserCollect extends Component<{}, {}>
for (let [num, mtl] of en.OverWriteMaterial)
en.OverWriteMaterial.set(num, material.Id);
}
en.Material = material.Id;
if (en instanceof BulkheadCeiling)
{
en.Material = material.Id;
en.SetDefaultMaterialAtAllSlot();
}
else
en.SetAllMaterialAtSlot(material.Id);
if (en instanceof Board)
{

Loading…
Cancel
Save