mirror of https://gitee.com/cf-fz/WebCAD.git
!2763 优化:在特性面板增加灯光参数批量调整功能
parent
0d41dc7d04
commit
3adf1ac6c4
@ -0,0 +1,656 @@
|
||||
import { Alignment, Button, Classes, FormGroup, Icon, InputGroup, Label, NumericInput, Popover, PopoverPosition, Position, Slider, Switch, Tooltip } from "@blueprintjs/core";
|
||||
import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { ColorResult } from "react-color";
|
||||
import SketchPicker from "react-color/lib/components/sketch/Sketch";
|
||||
import { MathUtils, Vector3 } from "three";
|
||||
import { Color } from "three/src/math/Color";
|
||||
import { app } from "../../ApplicationServices/Application";
|
||||
import { CoolDownTime } from "../../Common/CoolDownTime";
|
||||
import { ResourcesCDN_HOST } from "../../Common/HostUrl";
|
||||
import { KeyBoard } from "../../Common/KeyEnum";
|
||||
import { UpdateDraw } from "../../Common/Status";
|
||||
import { Intent } from "../../Common/Toaster";
|
||||
import { FixedNotZero } from "../../Common/Utils";
|
||||
import { DirectionalLight } from "../../DatabaseServices/Lights/DirectionalLight";
|
||||
import { Light } from "../../DatabaseServices/Lights/Light";
|
||||
import { PointLight } from "../../DatabaseServices/Lights/PointLight";
|
||||
import { RectAreaLight } from "../../DatabaseServices/Lights/RectAreaLight";
|
||||
import { SpotLight } from "../../DatabaseServices/Lights/SpotLight";
|
||||
import { CommandWrap, commandMachine } from "../../Editor/CommandMachine";
|
||||
import { CommandState } from "../../Editor/CommandState";
|
||||
import { PromptStatus } from "../../Editor/PromptResult";
|
||||
import { userConfig } from "../../Editor/UserConfig";
|
||||
import { BoardModalType } from "../../UI/Components/Board/BoardModalType";
|
||||
import { AppToaster } from "../../UI/Components/Toaster";
|
||||
import { PropertiesStore } from "../../UI/Components/ToolBar/PropertiesStore";
|
||||
import { LightStore } from "../../UI/Store/RightPanelStore/LightStore";
|
||||
import { Entitys2Data } from "../ExportData";
|
||||
import './LightBoxModel.less';
|
||||
|
||||
interface LightBoxModelProps
|
||||
{
|
||||
store: PropertiesStore;
|
||||
}
|
||||
|
||||
|
||||
@observer
|
||||
export class LightBoxModel extends React.Component<LightBoxModelProps, {}>
|
||||
{
|
||||
render()
|
||||
{
|
||||
let ents = this.props.store.GetEntitys();
|
||||
let lightType: BoardModalType;
|
||||
let currentLight = ents[0] as RectAreaLight | SpotLight | PointLight;
|
||||
let lightStore = new LightStore().InitLightData(ents[0] as RectAreaLight | SpotLight | PointLight);
|
||||
lightStore.IsDrawLight = true;
|
||||
let targetLightStores: LightStore[] = [];
|
||||
for (let i = 1; i < ents.length; i++)
|
||||
{
|
||||
let targetLight = ents[i];
|
||||
if (targetLight instanceof RectAreaLight || targetLight instanceof SpotLight || targetLight instanceof PointLight)
|
||||
{
|
||||
let targetLightStore = new LightStore().InitLightData(targetLight);
|
||||
targetLightStores.push(targetLightStore);
|
||||
}
|
||||
}
|
||||
|
||||
ents = ents.filter((entity, index) => index !== 0 && (entity instanceof SpotLight || entity instanceof RectAreaLight || entity instanceof PointLight));
|
||||
|
||||
if (currentLight instanceof SpotLight)
|
||||
{
|
||||
lightType = BoardModalType.SpotLight;
|
||||
}
|
||||
else if (currentLight instanceof RectAreaLight)
|
||||
{
|
||||
lightType = BoardModalType.RectAreaLight;
|
||||
}
|
||||
else if (currentLight instanceof PointLight)
|
||||
{
|
||||
lightType = BoardModalType.PointLight;
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="SpotLightModel" className={Classes.DIALOG_CONTAINER}
|
||||
style={{ width: 'auto', border: '1px solid #ccc', borderRadius: '5px', minHeight: 0 }}>
|
||||
<LightModel store={lightStore} lightType={lightType} lights={targetLightStores} />
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface LightConfigModelProps
|
||||
{
|
||||
store: LightStore;
|
||||
lightType: BoardModalType;
|
||||
lights: LightStore[];
|
||||
}
|
||||
interface ILightProperty
|
||||
{
|
||||
Target: Vector3;
|
||||
ShowHelper: boolean;
|
||||
CaseShadow: boolean;
|
||||
Color: string;
|
||||
Temperature: string;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class LightModel extends React.Component<LightConfigModelProps, {}>
|
||||
{
|
||||
@observable _Target: string = this.props.lightType === BoardModalType.PointLight ? "" : (this.props.store.currentSelectEnt as SpotLight | RectAreaLight).Target.sub(this.props.store.currentSelectEnt.Position).normalize().ceil().toArray().toString();
|
||||
@observable _Position: string = this.props.store.currentSelectEnt.Position.ceil().toArray().toString();
|
||||
private removeFuncs: Function[] = []; //移除注入
|
||||
private coolTime = new CoolDownTime;
|
||||
|
||||
handleSelectTarget = async (light: Light, isDirection?: boolean) =>
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
CommandWrap(async () =>
|
||||
{
|
||||
app.Editor.MaskManage.Clear();
|
||||
let ptRes = await app.Editor.GetPoint({
|
||||
Msg: "选择目标"
|
||||
});
|
||||
|
||||
if (ptRes.Status === PromptStatus.OK)
|
||||
{
|
||||
if (isDirection)
|
||||
{
|
||||
if (light instanceof SpotLight || light instanceof DirectionalLight)
|
||||
{
|
||||
light.Target = ptRes.Point;
|
||||
this._Target = ptRes.Point.clone().sub(this.props.store.currentSelectEnt.Position).normalize().ceil().toArray().toString();
|
||||
light.Update(UpdateDraw.Matrix);
|
||||
this.changeLightSettings('Target', ptRes.Point);
|
||||
}
|
||||
else if (light instanceof RectAreaLight)
|
||||
{
|
||||
light.Target = ptRes.Point;
|
||||
this.changeLightSettings('Target', ptRes.Point);
|
||||
}
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([light])));
|
||||
}
|
||||
}
|
||||
}, "target");
|
||||
};
|
||||
|
||||
//同步数据
|
||||
private SyncLight()
|
||||
{
|
||||
if (userConfig.synchronousEnable)
|
||||
this.coolTime.Debounce(() =>
|
||||
{
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([this.props.store.currentSelectEnt])));
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// 批量修改灯光属性
|
||||
changeLightSettings = (propertyName: keyof ILightProperty, propertyValue: ILightProperty[keyof ILightProperty]) =>
|
||||
{
|
||||
for (const light of this.props.lights)
|
||||
{
|
||||
let targetLightData = light.lightData;
|
||||
let targetLight = light.currentSelectEnt;
|
||||
if (targetLightData.hasOwnProperty(propertyName))
|
||||
{
|
||||
targetLight[propertyName] = propertyValue;
|
||||
targetLightData[propertyName] = propertyValue;
|
||||
}
|
||||
if (propertyName === 'Target')
|
||||
{
|
||||
if (targetLight instanceof SpotLight || targetLight instanceof DirectionalLight)
|
||||
{
|
||||
targetLight.Target = propertyValue as Vector3;
|
||||
this._Target = (propertyValue as Vector3).clone().sub(this.props.store.currentSelectEnt.Position).normalize().ceil().toArray().toString();
|
||||
targetLight.Update(UpdateDraw.Matrix);
|
||||
}
|
||||
else if (targetLight instanceof RectAreaLight)
|
||||
targetLight.Target = propertyValue as Vector3;;
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([targetLight])));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
render()
|
||||
{
|
||||
let lightData = this.props.store.lightData;
|
||||
let light = this.props.store.currentSelectEnt;
|
||||
return (
|
||||
<div className={Classes.DIALOG_CONTAINER}>
|
||||
<div className={Classes.DIALOG} style={{ height: "100%", margin: '0 auto', boxShadow: 'none', width: '100%' }}>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<div style={{ height: 25 }}>
|
||||
<Switch
|
||||
style={{ paddingLeft: '5px', paddingRight: '42px' }}
|
||||
checked={lightData.ShowHelper}
|
||||
label="显示灯光助手"
|
||||
onChange={e =>
|
||||
{
|
||||
CommandWrap(() =>
|
||||
{
|
||||
light.ShowHelper = !light.ShowHelper;
|
||||
this.changeLightSettings('ShowHelper', lightData.ShowHelper);
|
||||
}, "灯光助手显示/隐藏");
|
||||
app.Viewer.UpdateRender();
|
||||
lightData.ShowHelper = !lightData.ShowHelper;
|
||||
}}
|
||||
alignIndicator={Alignment.RIGHT}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ height: 25 }}>
|
||||
<Switch
|
||||
checked={lightData.CaseShadow}
|
||||
style={{ paddingLeft: '5px', paddingRight: '42px' }}
|
||||
label="阴影"
|
||||
onChange={e =>
|
||||
{
|
||||
CommandWrap(() =>
|
||||
{
|
||||
light.CaseShadow = !light.CaseShadow;
|
||||
this.changeLightSettings('CaseShadow', lightData.CaseShadow);
|
||||
}, "阴影显示/隐藏");
|
||||
app.Viewer.UpdateRender();
|
||||
lightData.CaseShadow = !lightData.CaseShadow;
|
||||
}}
|
||||
alignIndicator={Alignment.RIGHT}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
(this.props.lightType === BoardModalType.PointLight) ||
|
||||
<div style={{ paddingLeft: '5px', display: 'flex', alignItems: 'center' }}>
|
||||
<Label className="side-light-dir">方向:</Label>
|
||||
<input
|
||||
className={Classes.INPUT}
|
||||
style={{ width: '137px', height: '22px' }}
|
||||
value={this._Target}
|
||||
disabled
|
||||
/>
|
||||
<div style={{ margin: '0px 5px' }}>
|
||||
<Tooltip
|
||||
content="选择照射方向"
|
||||
position="top"
|
||||
>
|
||||
<Button
|
||||
icon="select"
|
||||
onClick={() => { this.handleSelectTarget(light, true); }}
|
||||
className="light-select-target"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="flex" style={{ paddingLeft: '3px', marginTop: '5px' }}>
|
||||
<Label style={{ float: "left", width: '33px', marginTop: '0' }}>颜色:</Label>
|
||||
<Popover
|
||||
position={PopoverPosition.TOP}
|
||||
minimal
|
||||
onClose={(e) => { e.preventDefault(); }}
|
||||
content={
|
||||
<SketchPicker
|
||||
color={lightData.Color.toUpperCase()}
|
||||
onChange={async (e: ColorResult) =>
|
||||
{
|
||||
const KEY = '修改颜色';
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
if (app.Database.hm.UndoData.CommandName !== KEY)
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "命令正在执行中!无法修改天光颜色!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER
|
||||
});
|
||||
return;
|
||||
}
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
} else
|
||||
{
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
this.props.store.currentSelectEnt.Color = new Color(e.hex.toString());
|
||||
app.Viewer.UpdateRender();
|
||||
this.SyncLight();
|
||||
lightData.Color = e.hex;
|
||||
this.changeLightSettings('Color', lightData.Color);
|
||||
}}
|
||||
onChangeComplete={() =>
|
||||
{
|
||||
const KEY = '修改颜色';
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}>
|
||||
<InputGroup
|
||||
value={lightData.Color.toUpperCase()}
|
||||
small
|
||||
readOnly
|
||||
className="light-panel-color layer-panel-input"
|
||||
leftIcon={
|
||||
<Icon
|
||||
icon='stop'
|
||||
size={20}
|
||||
color={this.props.store.lightData["Color"]} />
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<Label style={{ float: "left", paddingLeft: '5px', width: '36px', marginTop: '0' }}>色温:</Label>
|
||||
<Popover
|
||||
position={Position.TOP_LEFT}
|
||||
minimal
|
||||
onClose={(e) => { e.preventDefault(); }}
|
||||
>
|
||||
<InputGroup
|
||||
className="layer-panel-input"
|
||||
readOnly
|
||||
value={this.props.store.lightData.Temperature.toString() + 'K'}
|
||||
/>
|
||||
<div className='sun-colortemp'>
|
||||
<img alt='色温' draggable={false} src={`${ResourcesCDN_HOST}/colortemperature.webp`} />
|
||||
<Slider
|
||||
min={1700}
|
||||
max={12000}
|
||||
stepSize={1}
|
||||
labelStepSize={1775}
|
||||
showTrackFill={false}
|
||||
labelRenderer={() => (`${this.props.store.lightData.Temperature}K`)}
|
||||
value={parseInt(this.props.store.lightData.Temperature)}
|
||||
onChange={async (val) =>
|
||||
{
|
||||
|
||||
const KEY = "修改射灯色温";
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
if (app.Database.hm.UndoData.CommandName !== KEY)
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
AppToaster.show({
|
||||
message: "命令正在执行中!无法修改射灯色温!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
this.props.store.currentSelectEnt.Temperature = val;
|
||||
this.SyncLight();
|
||||
app.Viewer.UpdateRender();
|
||||
this.props.store.lightData.Temperature = val.toString();
|
||||
this.changeLightSettings('Temperature', this.props.store.lightData.Temperature);
|
||||
}}
|
||||
onRelease={() =>
|
||||
{
|
||||
const KEY = "修改射灯色温";
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
commandMachine.CommandEnd();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
{
|
||||
this.props.store.pars.map(([k, v]) =>
|
||||
{
|
||||
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 = 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 = 100;
|
||||
scale = 10;
|
||||
break;
|
||||
case "SourceRadius":
|
||||
case "SoftSourceRadius":
|
||||
max = 300;
|
||||
scale = 1;
|
||||
break;
|
||||
case "AttenuationRadius":
|
||||
min = 1;
|
||||
max = 100;
|
||||
scale = 10;
|
||||
break;
|
||||
case "Width":
|
||||
case "Height":
|
||||
min = 1;
|
||||
max = 50;
|
||||
noLim = true;
|
||||
scale = 100;
|
||||
break;
|
||||
case "BarnDoorLength":
|
||||
max = 100;
|
||||
scale = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return <UseInputAndSlider
|
||||
key={k}
|
||||
pars={[k, v]}
|
||||
store={this.props.store}
|
||||
max={max}
|
||||
min={min}
|
||||
scale={scale}
|
||||
isFloat={isFloat}
|
||||
noLim={noLim}
|
||||
lights={this.props.lights}
|
||||
/>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@observer
|
||||
export class UseInputAndSlider extends React.Component<{ pars: string[], store: LightStore; max: number; isFloat: boolean; min: number; scale: number; noLim: boolean; lights: LightStore[]; }, {}>
|
||||
{
|
||||
OldData: number = 0;
|
||||
private coolTime = new CoolDownTime;
|
||||
_InputRef = React.createRef<NumericInput>();
|
||||
private SyncLight()
|
||||
{
|
||||
if (userConfig.synchronousEnable)
|
||||
this.coolTime.Debounce(() =>
|
||||
{
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([this.props.store.currentSelectEnt])));
|
||||
}, 10);
|
||||
}
|
||||
|
||||
handleLightDataUpdate(store: LightStore, value: string)
|
||||
{
|
||||
switch (this.props.pars[0])
|
||||
{
|
||||
case "InnerConeAngle":
|
||||
store.lightData.InnerConeAngle = value;
|
||||
store.currentSelectEnt[this.props.pars[0]] = parseFloat(value);
|
||||
if (parseFloat(value) > parseFloat(store.lightData.Angle))
|
||||
{
|
||||
store.lightData.Angle = value;
|
||||
store.currentSelectEnt["Angle"] = MathUtils.degToRad(parseFloat(value));
|
||||
}
|
||||
store.currentSelectEnt.Update();
|
||||
break;
|
||||
case "Angle":
|
||||
store.lightData.Angle = value;
|
||||
store.currentSelectEnt["Angle"] = MathUtils.degToRad(parseFloat(value));
|
||||
if (parseFloat(value) < parseFloat(store.lightData.InnerConeAngle))
|
||||
{
|
||||
store.lightData.InnerConeAngle = value;
|
||||
store.currentSelectEnt["InnerConeAngle"] = parseFloat(value);
|
||||
}
|
||||
store.currentSelectEnt.Update();
|
||||
break;
|
||||
case "SpecularScale":
|
||||
store.lightData.SpecularScale = value;
|
||||
store.currentSelectEnt.SpecularScale = parseFloat(value);
|
||||
break;
|
||||
default:
|
||||
store.lightData[this.props.pars[0]] = value;
|
||||
store.currentSelectEnt[this.props.pars[0]] = parseFloat(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async SetValue(value: string)
|
||||
{
|
||||
const KEY = "修改灯光" + this.props.pars[1];;
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
if (app.Database.hm.UndoData.CommandName !== KEY)
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "命令正在执行中!无法修改灯光" + this.props.pars[1] + "!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
return;
|
||||
}
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
} else
|
||||
{
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
this.handleLightDataUpdate(this.props.store, value);
|
||||
|
||||
this.changeLightSliderSettings(this.props.pars[0], this.props.store.lightData[this.props.pars[0]]);
|
||||
this.SyncLight();
|
||||
app.Editor.UpdateScreen();
|
||||
}
|
||||
|
||||
|
||||
changeLightSliderSettings = (propertyName, propertyValue) =>
|
||||
{
|
||||
for (const light of this.props.lights)
|
||||
{
|
||||
let targetLightData = light.lightData;
|
||||
if (targetLightData.hasOwnProperty(propertyName))
|
||||
{
|
||||
this.handleLightDataUpdate(light, propertyValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render()
|
||||
{
|
||||
|
||||
let store = this.props.store;
|
||||
return (
|
||||
<FormGroup className="side-light-panel">
|
||||
<div className='inputslider side-light-input' style={{ marginBottom: '15px' }}>
|
||||
{
|
||||
["Height", "Width"].includes(this.props.pars[0]) ?
|
||||
<Label className="side-light-width">
|
||||
<div style={{ marginTop: -3, marginLeft: -24 }}>{this.props.pars[1]}:</div>
|
||||
</Label> :
|
||||
<Label style={{ float: "left", width: 70, marginTop: 1, textAlign: 'left', paddingLeft: '8px' }}>
|
||||
{this.props.pars[1]}:
|
||||
</Label>
|
||||
}
|
||||
<NumericInput
|
||||
ref={this._InputRef}
|
||||
tabIndex={1}
|
||||
min={this.props.min * this.props.scale}
|
||||
max={this.props.noLim ? 10e6 : this.props.max * this.props.scale}
|
||||
buttonPosition={"none"}
|
||||
value={this.props.store.lightData[this.props.pars[0]]}
|
||||
allowNumericCharactersOnly
|
||||
onKeyDown={(e) =>
|
||||
{
|
||||
if (e.keyCode === KeyBoard.Escape || e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
|
||||
{
|
||||
this._InputRef.current.inputElement.blur();
|
||||
}
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onValueChange={(numberValue, strValue, e) =>
|
||||
{
|
||||
let min = this.props.min * this.props.scale;
|
||||
let max = this.props.noLim ? 1e7 : this.props.max * this.props.scale;
|
||||
// 处理小数点 Data赋值不上传
|
||||
if (numberValue >= min && numberValue < max && strValue === numberValue + ".")
|
||||
{
|
||||
this.props.store.lightData[this.props.pars[0]] = numberValue + ".";
|
||||
return;
|
||||
}
|
||||
if (isNaN(numberValue) || numberValue > max) return;
|
||||
if (numberValue < min)
|
||||
{
|
||||
this.props.store.lightData[this.props.pars[0]] = numberValue;
|
||||
this.OldData = this.props.store.lightData[this.props.pars[0]];
|
||||
return;
|
||||
}
|
||||
else
|
||||
this.SetValue(FixedNotZero(numberValue, 1));
|
||||
|
||||
|
||||
}}
|
||||
onBlur={(e) =>
|
||||
{
|
||||
let min = this.props.min * this.props.scale;
|
||||
if (e.currentTarget.value[e.currentTarget.value.length - 1] === ".")
|
||||
{
|
||||
this.props.store.lightData[this.props.pars[0]] = this.props.store.currentSelectEnt[this.props.pars[0]];
|
||||
}
|
||||
if (this.props.store.lightData[this.props.pars[0]] < min)
|
||||
{
|
||||
if (this.OldData === this.props.store.currentSelectEnt[this.props.pars[0]])
|
||||
{
|
||||
this.props.store.lightData[this.props.pars[0]] = this.props.store.currentSelectEnt[this.props.pars[0]];
|
||||
return;
|
||||
}
|
||||
this.SetValue(FixedNotZero(min, 1));
|
||||
}
|
||||
|
||||
const KEY = '修改灯光' + this.props.pars[1];
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}}
|
||||
onFocus={(e) =>
|
||||
{
|
||||
e.target.select();
|
||||
}}
|
||||
/>
|
||||
<div style={{ marginLeft: -133, }}>
|
||||
<Slider
|
||||
className="side-light-container"
|
||||
min={this.props.min}
|
||||
max={this.props.max}
|
||||
stepSize={this.props.isFloat ? 0.1 : 1}
|
||||
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(() =>
|
||||
{
|
||||
this.SetValue((FixedNotZero(e, this.props.isFloat ? 1 : 0)));
|
||||
}, 0);
|
||||
}}
|
||||
onRelease={() =>
|
||||
{
|
||||
let coolTime = new CoolDownTime;
|
||||
coolTime.Debounce(() =>
|
||||
{
|
||||
const KEY = '修改灯光' + this.props.pars[1];
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}, 50);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
#SpotLightModel {
|
||||
width: 310px;
|
||||
font-size: 13px;
|
||||
|
||||
.bp3-dialog-body {
|
||||
padding: 5px;
|
||||
|
||||
.bp3-control.bp3-switch.bp3-align-right {
|
||||
padding-left: 24px;
|
||||
padding-right: 47px;
|
||||
}
|
||||
|
||||
>div {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.bp3-label.side-light-dir {
|
||||
float: left;
|
||||
width: 34px;
|
||||
margin-top: 9px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.side-light-width.bp3-label {
|
||||
width: 68px;
|
||||
}
|
||||
|
||||
.bp3-label .bp3-popover-wrapper {
|
||||
margin: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
.checkbox {
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-form-group {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bp3-form-group.side-light-panel {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.bp3-input-group.bp3-disabled.bp3-small.bp3-inline {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.bp3-popover-wrapper {
|
||||
.light-panel-color {
|
||||
.bp3-icon.bp3-icon-stop {
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-icon.bp3-icon-stop {
|
||||
margin-left: 13px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.layer-panel-input .bp3-input {
|
||||
width: 164px;
|
||||
height: 22px;
|
||||
margin-left: 4px;
|
||||
text-indent: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.bp3-control-group.bp3-numeric-input {
|
||||
float: left;
|
||||
|
||||
.bp3-input {
|
||||
height: 27px;
|
||||
width: 50px;
|
||||
margin-left: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.side-light-input {
|
||||
.bp3-control-group.bp3-numeric-input {
|
||||
.bp3-input {
|
||||
height: 22px;
|
||||
width: 133px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lg-pos {
|
||||
.bp3-button {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-slider {
|
||||
min-width: none;
|
||||
width: 130px;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
margin-top: 5px;
|
||||
margin-left: 140px;
|
||||
|
||||
.bp3-slider-axis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bp3-slider-handle {
|
||||
.bp3-slider-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-slider.side-light-container {
|
||||
margin-top: 30px;
|
||||
min-width: 188px;
|
||||
}
|
||||
|
||||
.bp3-list.bp3-list-unstyled {
|
||||
.pos {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.light-select-target.bp3-button {
|
||||
min-height: 20px;
|
||||
min-width: 20px;
|
||||
|
||||
span.bp3-icon {
|
||||
margin: -2px -7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-dialog-footer {
|
||||
padding: 7px 10px 7px 15px;
|
||||
border-top: 1px solid #dddddd;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
Loading…
Reference in new issue