diff --git a/src/Add-on/DrawLight/BatchModifyLights.ts b/src/Add-on/DrawLight/BatchModifyLights.ts new file mode 100644 index 000000000..49451abb5 --- /dev/null +++ b/src/Add-on/DrawLight/BatchModifyLights.ts @@ -0,0 +1,109 @@ +import { app } from "../../ApplicationServices/Application"; +import { EntitysUpdateWrap } from "../../Common/EntityUpdateWrap"; +import { PointLight } from "../../DatabaseServices/Lights/PointLight"; +import { RectAreaLight } from "../../DatabaseServices/Lights/RectAreaLight"; +import { SpotLight } from "../../DatabaseServices/Lights/SpotLight"; +import { Command } from "../../Editor/CommandMachine"; +import { PromptStatus } from "../../Editor/PromptResult"; +import { BoardModalType } from "../../UI/Components/Board/BoardModalType"; +import { ModalState } from "../../UI/Components/Modal/ModalInterface"; +import { IConfigStore } from "../../UI/Store/BoardStore"; +import { LightConfigModel } from "../../UI/Store/RightPanelStore/LightConfigModel"; +import { LightStore, PointLightStore, RectAreaLightStore, SpotLightStore } from "../../UI/Store/RightPanelStore/LightStore"; + +export class BatchModifyLights implements Command +{ + async exec() + { + let lightType: BoardModalType; + let configStore: IConfigStore; + let enRes = await app.Editor.GetEntity({ + Msg: "请选择第一个灯(需要修改的灯类型)", + NotNone: true, + Filter: { filterTypes: [RectAreaLight, SpotLight, PointLight] } + }); + if (enRes.Status !== PromptStatus.OK) return; + let currentLight = enRes.Entity as RectAreaLight | SpotLight | PointLight; + + app.Editor.SetSelection([currentLight]); + let lightStore = new LightStore().InitLightData(currentLight); + lightStore.IsDrawLight = true; + + if (currentLight instanceof SpotLight) + { + lightType = BoardModalType.SpotLight; + configStore = SpotLightStore.GetInstance(); + (configStore as SpotLightStore).lightStore = lightStore; + } + else if (currentLight instanceof RectAreaLight) + { + lightType = BoardModalType.RectAreaLight; + configStore = RectAreaLightStore.GetInstance(); + (configStore as RectAreaLightStore).lightStore = lightStore; + } + else if (currentLight instanceof PointLight) + { + lightType = BoardModalType.PointLight; + configStore = PointLightStore.GetInstance(); + (configStore as PointLightStore).lightStore = lightStore; + } + + let ssRes = await app.Editor.GetSelection({ + Msg: "请选择需要修改的灯", + Filter: { filterTypes: lightType === BoardModalType.RectAreaLight ? [RectAreaLight] : lightType === BoardModalType.SpotLight ? [SpotLight] : [PointLight] }, + }); + if (ssRes.Status !== PromptStatus.OK) return; + let lights = ssRes.SelectSet.SelectEntityList as (RectAreaLight | SpotLight | PointLight)[]; + + app.Editor.ModalManage.RenderModal(LightConfigModel, + { + store: lightStore, + lightType, + type: lightType + "Config", + configStore: configStore, + isNotModify: true, + }, { IsLightModal: true }); + + let state = await app.Editor.ModalManage.Wait(); + if (state.Status !== ModalState.Ok) return; + + EntitysUpdateWrap(lights, () => + { + for (const light of lights) + { + light.Color = currentLight.Color; + light.Temperature = currentLight.Temperature; + light.Intensity = currentLight.Intensity; + light.IndirectLightingIntensity = currentLight.IndirectLightingIntensity; + light.SpecularScale = currentLight.SpecularScale; + light.ShowHelper = currentLight.ShowHelper; + if (currentLight instanceof RectAreaLight && light instanceof RectAreaLight) + { + light.Width = currentLight.Width; + light.Height = currentLight.Height; + light.BarnDoorAngle = currentLight.BarnDoorAngle; + light.BarnDoorLength = currentLight.BarnDoorLength; + light.AttenuationRadius = currentLight.AttenuationRadius; + light.CaseShadow = currentLight.CaseShadow; + } + else if (currentLight instanceof SpotLight && light instanceof SpotLight) + { + light.Angle = currentLight.Angle; + light.InnerConeAngle = currentLight.InnerConeAngle; + light.SoftSourceRadius = currentLight.SoftSourceRadius; + light.SourceLength = currentLight.SourceLength; + light.SourceRadius = currentLight.SourceRadius; + light.AttenuationRadius = currentLight.AttenuationRadius; + light.CaseShadow = currentLight.CaseShadow; + light.Update(); + } + else if (currentLight instanceof PointLight && light instanceof PointLight) + { + light.SoftSourceRadius = currentLight.SoftSourceRadius; + light.SourceLength = currentLight.SourceLength; + light.SourceRadius = currentLight.SourceRadius; + } + } + }); + } +} diff --git a/src/Add-on/DrawLight/DrawPointLight.ts b/src/Add-on/DrawLight/DrawPointLight.ts index 8102f6350..b8f059fa9 100644 --- a/src/Add-on/DrawLight/DrawPointLight.ts +++ b/src/Add-on/DrawLight/DrawPointLight.ts @@ -28,7 +28,7 @@ export class DrawPointLight implements Command type: BoardModalType.PointLight + "Config", configStore: configStore, isNotModify: true, - }); + }, { IsLightModal: true }); setTimeout(() => { diff --git a/src/Add-on/DrawLight/DrawRectAreaLight.ts b/src/Add-on/DrawLight/DrawRectAreaLight.ts index 90e65d3ff..4b9c0f9f5 100644 --- a/src/Add-on/DrawLight/DrawRectAreaLight.ts +++ b/src/Add-on/DrawLight/DrawRectAreaLight.ts @@ -73,7 +73,7 @@ export class DrawRectAreaLight implements Command type: BoardModalType.RectAreaLight + "Config", configStore: configStore, isNotModify: true - }); + }, { IsLightModal: true }); setTimeout(() => { diff --git a/src/Add-on/DrawLight/DrawSpotLight.ts b/src/Add-on/DrawLight/DrawSpotLight.ts index 642e9e694..529c74d36 100644 --- a/src/Add-on/DrawLight/DrawSpotLight.ts +++ b/src/Add-on/DrawLight/DrawSpotLight.ts @@ -30,7 +30,7 @@ export class DrawSpotLight implements Command type: BoardModalType.SpotLight + "Config", configStore: configStore, isNotModify: true - }); + }, { IsLightModal: true }); setTimeout(() => { @@ -97,7 +97,7 @@ export class DrawSpotLight2 implements Command type: BoardModalType.SpotLight + "Config", configStore: configStore, isNotModify: true - }); + }, { IsLightModal: true }); setTimeout(() => { diff --git a/src/Common/CommandNames.ts b/src/Common/CommandNames.ts index a8fc54972..8ed9a9438 100644 --- a/src/Common/CommandNames.ts +++ b/src/Common/CommandNames.ts @@ -76,6 +76,7 @@ export enum CommandNames SpotLight = "SPOTLIGHT", SpotLight2 = "SPOTLIGHT2", RectLight = "RECTLIGHT", + BatchModifyLights = "BATCHMODIFYLIGHTS", Divide = "DIVIDE", Point = "POINT", AlignDim = "ALGINDIMEN", diff --git a/src/DatabaseServices/Lights/Light.ts b/src/DatabaseServices/Lights/Light.ts index 10c78bac1..d9497cf4b 100644 --- a/src/DatabaseServices/Lights/Light.ts +++ b/src/DatabaseServices/Lights/Light.ts @@ -74,7 +74,7 @@ export class Light extends Entity set Color(color: Color) { this.WriteAllObjectRecord(); - this._LightColor = color; + this._LightColor.set(color); this.Update(); } get ShowHelper() diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index 683ca9a09..dec028ee1 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -89,6 +89,7 @@ import { DrawEllipse } from "../Add-on/DrawEllipse"; import { DrawExtrude } from "../Add-on/DrawExtrude"; import { DrawFloor } from "../Add-on/DrawFloor"; import { DrawGripStretch } from "../Add-on/DrawGripStretch"; +import { BatchModifyLights } from "../Add-on/DrawLight/BatchModifyLights"; import { DrawPointLight } from "../Add-on/DrawLight/DrawPointLight"; import { DrawRectAreaLight } from "../Add-on/DrawLight/DrawRectAreaLight"; import { DrawSpotLight, DrawSpotLight2 } from "../Add-on/DrawLight/DrawSpotLight"; @@ -428,6 +429,7 @@ export function registerCommand() commandMachine.RegisterCommand(CommandNames.SpotLight, new DrawSpotLight()); commandMachine.RegisterCommand(CommandNames.SpotLight2, new DrawSpotLight2()); commandMachine.RegisterCommand(CommandNames.RectLight, new DrawRectAreaLight()); + commandMachine.RegisterCommand(CommandNames.BatchModifyLights, new BatchModifyLights()); commandMachine.RegisterCommand("ptcopy", new Command_CopyPoint()); diff --git a/src/Editor/DbClick/DbClick.ts b/src/Editor/DbClick/DbClick.ts index 072c5ac21..6aac10428 100644 --- a/src/Editor/DbClick/DbClick.ts +++ b/src/Editor/DbClick/DbClick.ts @@ -84,7 +84,7 @@ export class DbClickManager extends Singleton if (pickEnt instanceof Light) { const width = 500; - const height = 500; + const height = 600; let lightStore = LightStore.GetInstance(); lightStore.IsDrawLight = false; lightStore.InitLightData(pickEnt); @@ -102,16 +102,19 @@ export class DbClickManager extends Singleton { lightType = BoardModalType.SpotLight; configStore = SpotLightStore.GetInstance(); + (configStore as SpotLightStore).lightStore = lightStore; } else if (pickEnt instanceof RectAreaLight) { lightType = BoardModalType.RectAreaLight; configStore = RectAreaLightStore.GetInstance(); + (configStore as RectAreaLightStore).lightStore = lightStore; } else if (pickEnt instanceof PointLight) { lightType = BoardModalType.PointLight; configStore = PointLightStore.GetInstance(); + (configStore as PointLightStore).lightStore = lightStore; } let p = app.Viewer.WorldToScreen(pickEnt.Position); let left = Math.min(p.x + app.Viewer.canvasContainer.offsetLeft + 10, window.innerWidth - width); @@ -120,7 +123,7 @@ export class DbClickManager extends Singleton CADModal.ModalOldPosition.top = `${top > 0 ? top : 0}px`; app.Editor.ModalManage.RenderModeless(LightConfigModel, - { store: lightStore, configStore, lightType, type: "lightModel" }, { position: ModalPosition.Old }); + { store: lightStore, configStore, lightType, type: "lightModel" }, { position: ModalPosition.Old, IsLightModal: true }); } else if (pickEnt instanceof Text || pickEnt instanceof RoomRegion) { diff --git a/src/UI/Components/CommandPanel/CommandList.ts b/src/UI/Components/CommandPanel/CommandList.ts index cb4f997a1..263c25082 100644 --- a/src/UI/Components/CommandPanel/CommandList.ts +++ b/src/UI/Components/CommandPanel/CommandList.ts @@ -972,6 +972,16 @@ export const CommandList: ICommand[] = [ // enName: "Rectangular light", chDes: "均匀的矩形面光源", }, + { + // icon: IconEnum.RectLight, + typeId: "dg", + link: `#`, + defaultCustom: "BML", + command: CommandNames.BatchModifyLights, + type: "灯光", + chName: "批量修改灯光", + chDes: "批量修改灯光属性", + }, //排钻命令 { diff --git a/src/UI/Components/Modal/CadModal.tsx b/src/UI/Components/Modal/CadModal.tsx index 20412d57d..8b78c72dc 100644 --- a/src/UI/Components/Modal/CadModal.tsx +++ b/src/UI/Components/Modal/CadModal.tsx @@ -94,7 +94,7 @@ export class CADModal } Render(Component: React.ComponentType, props: T, option: IModalProps = {}) { - const { canMinimize = true, resizable = false, position = ModalPosition.Center, isModal = false, isMax = false, canForceMax = false } = option; + const { canMinimize = true, resizable = false, position = ModalPosition.Center, isModal = false, isMax = false, canForceMax = false, IsLightModal = false } = option; let key = props?.type ?? GetCompoentObjectIdString(Component); //校验Key @@ -181,6 +181,7 @@ export class CADModal this.canResize = resizable; this.canMinimize = canMinimize; this.IsModal = isModal; + this.IsLightModal = IsLightModal; this.SetPosition(position); this._canForceMax = canForceMax; this.container.focus(); diff --git a/src/UI/Components/Modal/ModalsManage.ts b/src/UI/Components/Modal/ModalsManage.ts index 22645abc4..0f278f62b 100644 --- a/src/UI/Components/Modal/ModalsManage.ts +++ b/src/UI/Components/Modal/ModalsManage.ts @@ -37,7 +37,8 @@ export interface IModalProps root?: CADModal; /**可以在命令执行中放大 */ canForceMax?: boolean; - + /**是否为灯光模板 */ + IsLightModal?: boolean; minWidth?: number; minHeight?: number; } diff --git a/src/UI/Css/style.less b/src/UI/Css/style.less index cbee6138a..b0c0a2fe7 100644 --- a/src/UI/Css/style.less +++ b/src/UI/Css/style.less @@ -1063,14 +1063,14 @@ img { } #SpotLightModel { - width : 300px; + width : 310px; font-size: 13px; .bp3-dialog-body { padding: 5px; .bp3-control.bp3-switch.bp3-align-right { - padding-left : 14px; + padding-left : 24px; padding-right: 47px; } @@ -1081,16 +1081,25 @@ img { input { width : 100px; height : 27px; - margin-left: 10px; } .bp3-label { float : left; - width : 56px; + width : 76px; margin-top: 5px; text-align: center; } + .bp3-label .bp3-popover-wrapper{ + margin: 0; + width: 16px; + height: 16px; + + .checkbox{ + margin: 0 0 0 5px; + } + } + .bp3-form-group { margin: 0; } @@ -1108,7 +1117,7 @@ img { .bp3-input { width : 100px; height : 27px; - margin-left: 10px; + margin-left: 0; text-indent: 18px; } } @@ -1119,7 +1128,7 @@ img { .bp3-input { height : 27px; width : 50px; - margin-left: 10px; + margin-left: 0; padding : 10px; } } @@ -1136,7 +1145,7 @@ img { height : auto; position : absolute; margin-top : 5px; - margin-left: 130px; + margin-left: 140px; .bp3-slider-axis { display: none; @@ -1157,7 +1166,7 @@ img { } .bp3-dialog-footer { - padding : 7px 10px 7px 10px; + padding : 7px 10px 7px 15px; border-top : 1px solid #dddddd; background-color: white; } diff --git a/src/UI/Store/RightPanelStore/LightConfigModel.tsx b/src/UI/Store/RightPanelStore/LightConfigModel.tsx index 26d906d0e..3bae878e5 100644 --- a/src/UI/Store/RightPanelStore/LightConfigModel.tsx +++ b/src/UI/Store/RightPanelStore/LightConfigModel.tsx @@ -1,4 +1,4 @@ -import { Alignment, Button, Classes, FormGroup, Icon, InputGroup, Intent, Label, NumericInput, Popover, PopoverPosition, Position, Slider, Switch, Tooltip, UL } from "@blueprintjs/core"; +import { Alignment, Button, Checkbox, Classes, FormGroup, Icon, InputGroup, Intent, Label, NumericInput, Popover, PopoverPosition, Position, Slider, Switch, Tooltip, UL } from "@blueprintjs/core"; import { observable } from "mobx"; import { observer } from "mobx-react"; import React from "react"; @@ -25,7 +25,7 @@ import { Config_ModalType, UserConfig } from "../../Components/Board/UserConfig" import { ModalState } from "../../Components/Modal/ModalInterface"; import { AppToaster } from "../../Components/Toaster"; import { IConfigStore } from "../BoardStore"; -import { LightStore } from "./LightStore"; +import { LightStore, RectAreaLightStore } from "./LightStore"; @observer export class LightConfigModel extends React.Component<{ store: LightStore; configStore: IConfigStore; lightType: BoardModalType; isNotModify?: boolean; type: string; }, {}> @@ -49,11 +49,9 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi e.stopPropagation(); }) ); - setTimeout(() => { app.Editor.ModalManage.CurrentModal.IsLightModal = true; }, 0); } componentWillUnmount() { - app.Editor.ModalManage.CurrentModal.IsLightModal = false; for (let f of this.removeFuncs) f(); this.removeFuncs.length = 0; @@ -127,25 +125,22 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi />
- - { -
- - { - if (!this.props.isNotModify) - CommandWrap(() => - { - light.ShowHelper = !light.ShowHelper; - }, "灯光助手显示/隐藏"); - lightData.ShowHelper = !lightData.ShowHelper; - }} - alignIndicator={Alignment.RIGHT} - /> -
- } +
+ + { + if (!this.props.isNotModify) + CommandWrap(() => + { + light.ShowHelper = !light.ShowHelper; + }, "灯光助手显示/隐藏"); + lightData.ShowHelper = !lightData.ShowHelper; + }} + alignIndicator={Alignment.RIGHT} + /> +
{ - (this.props.lightType === BoardModalType.PointLight) ||
+ (this.props.lightType === BoardModalType.PointLight) || +
@@ -208,7 +204,7 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi
@@ -285,6 +281,7 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi { e.preventDefault(); }} >
@@ -365,43 +363,53 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi let max: number = 200; let min: number = 0; let isFloat: boolean = false; //stepsize 是否为0.1 + let scale: number = 1; let noLim: boolean = false; switch (k) { case "Intensity": - max = 2000; + max = 200; + scale = 10; break; case "IndirectLightingIntensity": max = 6; + scale = 1; break; case "Angle": case "InnerConeAngle": case "BarnDoorAngle": max = 90; + scale = 1; break; case "SpecularScale": max = 1; isFloat = true; + scale = 1; break; case "SourceLength": - max = 1000; + max = 100; + scale = 10; break; case "SourceRadius": case "SoftSourceRadius": max = 300; + scale = 1; break; case "AttenuationRadius": - min = 10; - max = 1000; + min = 1; + max = 100; + scale = 10; break; case "Width": case "Height": min = 1; - max = 5000; + max = 50; noLim = true; + scale = 100; break; case "BarnDoorLength": max = 100; + scale = 1; break; default: break; @@ -412,6 +420,7 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi store={this.props.store} max={max} min={min} + scale={scale} isFloat={isFloat} noLim={noLim} isNotModify={this.props.isNotModify} @@ -450,7 +459,7 @@ export class LightConfigModel extends React.Component<{ store: LightStore; confi } @observer -export class InputAndSlider extends React.Component<{ pars: string[], store: LightStore; max: number; isFloat: boolean; min: number; noLim: boolean; isNotModify: boolean; }, {}> +export class InputAndSlider extends React.Component<{ pars: string[], store: LightStore; max: number; isFloat: boolean; min: number; scale: number; noLim: boolean; isNotModify: boolean; }, {}> { OldData: number = 0; private coolTime = new CoolDownTime; @@ -561,13 +570,40 @@ export class InputAndSlider extends React.Component<{ pars: string[], store: Lig render() { + let store = this.props.store; + let rectStore = RectAreaLightStore.GetInstance(); return ( -
- +
+ { + ["Height", "Width"].includes(this.props.pars[0]) ? + : + + } = this.props.max ? this.props.max : parseFloat(this.props.store.lightData[this.props.pars[0]])} + value={parseFloat(store.lightData[this.props.pars[0]]) / this.props.scale > this.props.max ? this.props.max : parseFloat(store.lightData[this.props.pars[0]]) / this.props.scale} onChange={(e) => { + e = e * this.props.scale; let coolTime = new CoolDownTime; coolTime.Debounce(() => { diff --git a/src/UI/Store/RightPanelStore/LightStore.ts b/src/UI/Store/RightPanelStore/LightStore.ts index 00c6270b2..1582d631b 100644 --- a/src/UI/Store/RightPanelStore/LightStore.ts +++ b/src/UI/Store/RightPanelStore/LightStore.ts @@ -90,9 +90,9 @@ export class LightStore implements IConfigStore @observable ShowSunLight = true; @observable ShowHemiLight = true; @observable ShowExposure = true; - @observable currentSelectEnt: Light = undefined; - @observable title = ""; - @observable pars: [string, string][] = []; + currentSelectEnt: Light = undefined; + title = ""; + pars: [string, string][] = []; @observable lightData: LightModalState = {}; @observable ambientLightData = { Color: "#" + app.Database.AmbientLight.Color.getHexString(), @@ -226,6 +226,7 @@ export class LightStore implements IConfigStore Object.assign(this.lightData, newState); this.currentSelectEnt = light; } + return this; } private WatchLightEvent() @@ -469,6 +470,8 @@ export class RectAreaLightStore implements IConfigStore @observable m_Option: RectAreaLightOption = { ...DefaultRectAreaLightOption }; @observable configsNames: string[] = []; lightStore: LightStore; + @observable isLockWidth: boolean = false; + @observable isLockHeight: boolean = false; InitOption() { Object.assign(this.m_Option, DefaultRectAreaLightOption); @@ -516,8 +519,10 @@ export class RectAreaLightStore implements IConfigStore lightStore.lightData.AttenuationRadius = cof.option.AttenuationRadius.toString(); lightStore.lightData.CaseShadow = cof.option.CaseShadow; lightStore.lightData.ShowHelper = cof.option.ShowHelper; - lightStore.lightData.Height = cof.option.Height.toString(); - lightStore.lightData.Width = cof.option.Width.toString(); + if (!this.isLockHeight) + lightStore.lightData.Height = cof.option.Height.toString(); + if (!this.isLockWidth) + lightStore.lightData.Width = cof.option.Width.toString(); let rectAreaLight = lightStore.currentSelectEnt as RectAreaLight; if (!lightStore.IsDrawLight) { @@ -543,8 +548,10 @@ export class RectAreaLightStore implements IConfigStore rectAreaLight.Temperature = cof.option.temperature; rectAreaLight.IndirectLightingIntensity = cof.option.IndirectLightingIntensity; rectAreaLight.SpecularScale = cof.option.SpecularScale; - rectAreaLight.Width = cof.option.Width; - rectAreaLight.Height = cof.option.Height; + if (!this.isLockWidth) + rectAreaLight.Width = cof.option.Width; + if (!this.isLockHeight) + rectAreaLight.Height = cof.option.Height; rectAreaLight.BarnDoorAngle = cof.option.BarnDoorAngle; rectAreaLight.BarnDoorLength = cof.option.BarnDoorLength; rectAreaLight.AttenuationRadius = cof.option.AttenuationRadius;