mirror of https://gitee.com/cf-fz/WebCAD.git
!1643 优化:重构太阳光助手、射灯助手,更新灯光在WebCAD中的显示
parent
b52c8a83e5
commit
0b69adc0c3
@ -0,0 +1,102 @@
|
||||
import { BackSide, BufferGeometry, Color, Float32BufferAttribute, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, RectAreaLight as TRectAreaLight } from "three";
|
||||
|
||||
/**
|
||||
* This helper must be added as a child of the light (移植threejs最新的版本)
|
||||
*/
|
||||
export class RectAreaLightHelper extends Line
|
||||
{
|
||||
light: TRectAreaLight;
|
||||
color: Color;
|
||||
material: LineBasicMaterial;
|
||||
children: [Mesh];
|
||||
constructor(light: TRectAreaLight, color: Color)
|
||||
{
|
||||
const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0,
|
||||
0.618, 0.618, 0,
|
||||
0.618, 0.618, -100,
|
||||
0.618, 0.618, 0,
|
||||
|
||||
|
||||
-0.618, 0.618, 0,
|
||||
-1, 1, 0,
|
||||
-0.618, 0.618, 0,
|
||||
-0.618, 0.618, -100,
|
||||
-0.618, 0.618, 0,
|
||||
|
||||
-0.618, -0.618, 0,
|
||||
-1, -1, 0,
|
||||
-0.618, -0.618, 0,
|
||||
-0.618, -0.618, -100,
|
||||
-0.618, -0.618, 0,
|
||||
|
||||
|
||||
0.618, -0.618, 0,
|
||||
1, -1, 0,
|
||||
0.618, -0.618, 0,
|
||||
0.618, -0.618, -100,
|
||||
0.618, -0.618, 0,
|
||||
|
||||
|
||||
0.618, 0.618, 0
|
||||
];
|
||||
|
||||
const geometry = new BufferGeometry();
|
||||
geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
const material = new LineBasicMaterial({ fog: false });
|
||||
|
||||
super(geometry, material);
|
||||
|
||||
this.light = light;
|
||||
this.color = color; // optional hardwired color for the helper
|
||||
this.type = 'RectAreaLightHelper';
|
||||
|
||||
//
|
||||
const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
|
||||
|
||||
const geometry2 = new BufferGeometry();
|
||||
geometry2.setAttribute('position', new Float32BufferAttribute(positions2, 3));
|
||||
geometry2.computeBoundingSphere();
|
||||
|
||||
this.add(new Mesh(geometry2, new MeshBasicMaterial({ side: BackSide, fog: false, transparent: true, opacity: 0.8 })));
|
||||
}
|
||||
|
||||
updateMatrixWorld()
|
||||
{
|
||||
this.scale.set(0.5 * this.light.width, 0.5 * this.light.height, 1);
|
||||
|
||||
if (this.color !== undefined)
|
||||
{
|
||||
this.material.color.set(this.color);
|
||||
//@ts-ignore
|
||||
this.children[0].material.color.set(this.color);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.material.color.copy(this.light.color).multiplyScalar(this.light.intensity);
|
||||
|
||||
// prevent hue shift
|
||||
const c = this.material.color;
|
||||
const max = Math.max(c.r, c.g, c.b);
|
||||
if (max > 1)
|
||||
c.multiplyScalar(1 / max);
|
||||
//@ts-ignore
|
||||
this.children[0].material.color.copy(this.material.color);
|
||||
}
|
||||
|
||||
// ignore world scale on light
|
||||
this.matrixWorld.extractRotation(this.light.matrixWorld).scale(this.scale).copyPosition(this.light.matrixWorld);
|
||||
|
||||
this.children[0].matrixWorld.copy(this.matrixWorld);
|
||||
}
|
||||
|
||||
dispose()
|
||||
{
|
||||
this.geometry.dispose();
|
||||
this.material.dispose();
|
||||
this.children[0].geometry.dispose();
|
||||
//@ts-ignore
|
||||
this.children[0].material.dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
import { BufferGeometry, Float32BufferAttribute, LineBasicMaterial, LineSegments, MathUtils, Matrix4, Object3D, SpotLight, Vector3 } from 'three';
|
||||
|
||||
export class SpotLightHelper extends Object3D
|
||||
{
|
||||
light: SpotLight;
|
||||
matrix: Matrix4;
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
matrixAutoUpdate: boolean;
|
||||
|
||||
cone: LineSegments[];
|
||||
material: LineBasicMaterial[];
|
||||
InnerConeAngle: number;
|
||||
|
||||
constructor(light: SpotLight)
|
||||
{
|
||||
const geometry = new BufferGeometry();
|
||||
const positions = [
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 1, 0, 1,
|
||||
0, 0, 0, - 1, 0, 1,
|
||||
0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, - 1, 1
|
||||
];
|
||||
for (let i = 0, j = 1, l = 32; i < l; i++, j++)
|
||||
{
|
||||
|
||||
const p1 = (i / l) * Math.PI * 2;
|
||||
const p2 = (j / l) * Math.PI * 2;
|
||||
|
||||
positions.push(
|
||||
Math.cos(p1), Math.sin(p1), 1,
|
||||
Math.cos(p2), Math.sin(p2), 1
|
||||
);
|
||||
|
||||
}
|
||||
geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
|
||||
|
||||
super();
|
||||
this.light = light;
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
this.matrix = light.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
this.material = [];
|
||||
this.material[0] = new LineBasicMaterial({ fog: false });;
|
||||
this.material[1] = new LineBasicMaterial({ fog: false });;
|
||||
this.InnerConeAngle = 0;
|
||||
this.cone = [];
|
||||
this.cone[0] = new LineSegments(geometry, this.material[0]);
|
||||
this.cone[1] = new LineSegments(geometry, this.material[1]);
|
||||
this.add(this.cone[0], this.cone[1]);
|
||||
}
|
||||
|
||||
dispose()
|
||||
{
|
||||
this.InnerConeAngle = undefined;
|
||||
this.material[0].dispose();
|
||||
this.material[1].dispose();
|
||||
this.cone[0].geometry.dispose();
|
||||
this.cone[1].geometry.dispose();
|
||||
//@ts-ignore
|
||||
this.cone[0].material.dispose();
|
||||
//@ts-ignore
|
||||
this.cone[1].material.dispose();
|
||||
}
|
||||
|
||||
update()
|
||||
{
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
const coneLength = this.light.distance ? this.light.distance : 1000;
|
||||
const coneWidth1 = coneLength * Math.tan(this.light.angle);
|
||||
const coneWidth2 = coneLength * Math.tan(MathUtils.degToRad(this.InnerConeAngle));
|
||||
|
||||
this.cone[0].scale.set(coneWidth1, coneWidth1, coneLength);
|
||||
this.cone[1].scale.set(coneWidth2, coneWidth2, coneLength);
|
||||
|
||||
this.cone[0].lookAt(new Vector3().setFromMatrixPosition(this.light.target.matrixWorld));
|
||||
this.cone[1].lookAt(new Vector3().setFromMatrixPosition(this.light.target.matrixWorld));
|
||||
|
||||
//@ts-ignore
|
||||
this.cone[0].material.color.set(this.light.color).multiplyScalar(0.3);
|
||||
|
||||
//@ts-ignore
|
||||
this.cone[1].material.color.set(this.light.color);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Color, DirectionalLight, DirectionalLightHelper, LineBasicMaterial, Matrix4, Mesh, SphereBufferGeometry } from "three";
|
||||
|
||||
export class SunLightHelper extends DirectionalLightHelper
|
||||
{
|
||||
light: DirectionalLight;
|
||||
|
||||
children: [Mesh];
|
||||
size: number;
|
||||
/**
|
||||
* @default undefined
|
||||
*/
|
||||
color: Color | string | number;
|
||||
matrix: Matrix4;
|
||||
|
||||
constructor(light: DirectionalLight, size: number, color?: Color)
|
||||
{
|
||||
const geometry = new SphereBufferGeometry(1, 16, 16);
|
||||
const material = new LineBasicMaterial({ fog: false });
|
||||
material.color = light.color;
|
||||
super(light, size, color);
|
||||
|
||||
this.children[0].geometry = geometry.scale(400, 400, 400);
|
||||
this.children[0].material = material;
|
||||
|
||||
this.light = light;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
matrixAutoUpdate: boolean;
|
||||
}
|
@ -0,0 +1,487 @@
|
||||
import { Alignment, Button, 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";
|
||||
import { ColorResult, SketchPicker } from "react-color";
|
||||
import { Color, MathUtils } from "three";
|
||||
import { Entitys2Data } from "../../../Add-on/ExportData";
|
||||
import { app } from "../../../ApplicationServices/Application";
|
||||
import { ResourcesCDN_HOST } from "../../../Common/HostUrl";
|
||||
import { FixedNotZero } from "../../../Common/Utils";
|
||||
import { DirectionalLight } from "../../../DatabaseServices/Lights/DirectionalLight";
|
||||
import { Light } from "../../../DatabaseServices/Lights/Light";
|
||||
import { RectAreaLight } from "../../../DatabaseServices/Lights/RectAreaLight";
|
||||
import { SpotLight } from "../../../DatabaseServices/Lights/SpotLight";
|
||||
import { commandMachine, CommandWrap } from "../../../Editor/CommandMachine";
|
||||
import { CommandState } from "../../../Editor/CommandState";
|
||||
import { PromptStatus } from "../../../Editor/PromptResult";
|
||||
import { userConfig } from "../../../Editor/UserConfig";
|
||||
import { AppToaster } from "../../Components/Toaster";
|
||||
import { LightStore } from "./LightStore";
|
||||
|
||||
@observer
|
||||
export class SpotLightModel extends React.Component<{ store: LightStore; isPointLight: boolean; }, {}>
|
||||
{
|
||||
@observable _Target: string = this.props.isPointLight ? (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();
|
||||
@observable _ShowHelper: boolean = this.props.store.currentSelectEnt.ShowHelper;
|
||||
@observable _CaseShadow: boolean = this.props.store.currentSelectEnt.CaseShadow;
|
||||
|
||||
handleSelectTarget = async (light: Light, isDirection?: boolean, isPosition?: boolean) =>
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
let model = app.Editor.ModalManage.CurrentModal;
|
||||
model.Minimize();
|
||||
CommandWrap(async () =>
|
||||
{
|
||||
app.Editor.MaskManage.Clear();
|
||||
let ptRes = await app.Editor.GetPoint({
|
||||
Msg: "选择目标"
|
||||
});
|
||||
|
||||
if (ptRes.Status === PromptStatus.OK)
|
||||
{
|
||||
if (isDirection)
|
||||
{
|
||||
(light as SpotLight | DirectionalLight).Target = ptRes.Point;
|
||||
app.Editor.UpdateScreen();
|
||||
this._Target = ptRes.Point.clone().sub(this.props.store.currentSelectEnt.Position).normalize().ceil().toArray().toString();
|
||||
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([light])));
|
||||
}
|
||||
if (isPosition)
|
||||
{
|
||||
light.WriteAllObjectRecord();
|
||||
this.props.store.lightData.x = ptRes.Point.x.toString();
|
||||
this.props.store.lightData.y = ptRes.Point.y.toString();
|
||||
this.props.store.lightData.z = ptRes.Point.z.toString();
|
||||
light.Position = ptRes.Point;
|
||||
this._Position = ptRes.Point.ceil().toArray().toString();;
|
||||
}
|
||||
}
|
||||
}, "target");
|
||||
};
|
||||
|
||||
//同步数据
|
||||
private SyncLight()
|
||||
{
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([this.props.store.currentSelectEnt])));
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
let lightData = this.props.store.lightData;
|
||||
let light = this.props.store.currentSelectEnt;
|
||||
return (
|
||||
<div id="SpotLightModel" className={Classes.DIALOG_CONTAINER}>
|
||||
<div className={Classes.DIALOG} style={{ height: "100%" }}>
|
||||
<div className={Classes.DIALOG_HEADER} data-id="dragArea">
|
||||
<Icon icon="flash" iconSize={18} />
|
||||
<h4 className={Classes.HEADING}>{this.props.store.title}设置</h4>
|
||||
<Button
|
||||
icon="cross"
|
||||
aria-label="Close"
|
||||
minimal={true}
|
||||
onClick={() => { app.Editor.ModalManage.Destory(); }}
|
||||
/>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
|
||||
{
|
||||
!this.props.isPointLight || <div style={{ height: 25 }}>
|
||||
<Switch
|
||||
checked={this._ShowHelper}
|
||||
label="显示灯光助手"
|
||||
onChange={e =>
|
||||
{
|
||||
CommandWrap(() =>
|
||||
{
|
||||
this._ShowHelper = !this._ShowHelper;
|
||||
light.ShowHelper = !light.ShowHelper;
|
||||
}, "灯光助手显示/隐藏");
|
||||
}}
|
||||
alignIndicator={Alignment.RIGHT}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<div style={{ height: 25 }}>
|
||||
<Switch
|
||||
checked={this._CaseShadow}
|
||||
label="阴影"
|
||||
onChange={e =>
|
||||
{
|
||||
CommandWrap(() =>
|
||||
{
|
||||
this._CaseShadow = !this._CaseShadow;
|
||||
light.CaseShadow = !light.CaseShadow;
|
||||
}, "阴影显示/隐藏");
|
||||
}}
|
||||
alignIndicator={Alignment.RIGHT}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
!this.props.isPointLight || <div>
|
||||
<div>
|
||||
<Label style={{ float: "left" }}>方向:</Label>
|
||||
<input
|
||||
className={Classes.INPUT}
|
||||
style={{ height: 27, marginLeft: 10 }}
|
||||
value={this._Target}
|
||||
disabled
|
||||
/>
|
||||
<div style={{ position: "absolute", right: "48px", marginTop: "-28.5px" }}>
|
||||
<Tooltip
|
||||
content="选择照射方向"
|
||||
position="top"
|
||||
>
|
||||
<Button
|
||||
icon="select"
|
||||
onClick={() => { this.handleSelectTarget(light, true); }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ float: "left", position: "absolute", right: "4%" }}>
|
||||
<Tooltip
|
||||
content="同时选择照射方向和位置"
|
||||
position="right"
|
||||
>
|
||||
<Button
|
||||
style={{ marginTop: "-29.5px", height: "65px" }}
|
||||
icon="select"
|
||||
onClick={() => { this.handleSelectTarget(light, true, true); }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="lg-pos">
|
||||
<Label style={{ float: "left" }}>位置:</Label>
|
||||
<UL className={Classes.LIST_UNSTYLED}>
|
||||
<div className="pos">
|
||||
<input
|
||||
className={Classes.INPUT}
|
||||
style={{ height: 27, marginLeft: 10 }}
|
||||
value={this._Position}
|
||||
disabled
|
||||
/>
|
||||
<div style={{ position: "absolute", right: this.props.isPointLight ? 48 : 11, marginTop: "-1.5px" }}>
|
||||
<Tooltip content="选择位置">
|
||||
<Button
|
||||
icon="select"
|
||||
onClick={() => { this.handleSelectTarget(light, false, true); }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</UL>
|
||||
</div>
|
||||
<div>
|
||||
<Label style={{ float: "left" }}>颜色:</Label>
|
||||
<Popover
|
||||
position={PopoverPosition.TOP}
|
||||
minimal
|
||||
content={
|
||||
<SketchPicker
|
||||
color={lightData.Color.toUpperCase()}
|
||||
onChange={(e: ColorResult) =>
|
||||
{
|
||||
const KEY = '修改颜色';
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
if (app.Database.hm.UndoData.CommandName !== KEY)
|
||||
{
|
||||
app.Editor.ModalManage.EndExecingCmd().then(() =>
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "命令正在执行中!无法修改天光颜色!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
this.props.store.currentSelectEnt.Color = new Color(e.hex.toString());
|
||||
lightData.Color = e.hex;
|
||||
app.Viewer.UpdateRender();
|
||||
this.SyncLight();
|
||||
}}
|
||||
onChangeComplete={() =>
|
||||
{
|
||||
const KEY = '修改颜色';
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}>
|
||||
<InputGroup
|
||||
value={lightData.Color.toUpperCase()}
|
||||
small
|
||||
leftIcon={
|
||||
<Icon
|
||||
icon='stop'
|
||||
size={20}
|
||||
color={this.props.store.lightData["Color"]} />
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
<div>
|
||||
<Label style={{ float: "left" }}>色温:</Label>
|
||||
<Popover
|
||||
position={Position.TOP_LEFT}
|
||||
minimal
|
||||
>
|
||||
<InputGroup
|
||||
value={this.props.store.lightData.Temperature.toString() + 'K'}
|
||||
/>
|
||||
<div className='sun-colortemp'>
|
||||
<img alt='色温' draggable={false} src={`${ResourcesCDN_HOST}/colortemperature.webp`} />
|
||||
<Slider
|
||||
min={1800}
|
||||
max={16000}
|
||||
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.props.store.lightData.Temperature = val.toString();
|
||||
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([this.props.store.currentSelectEnt])));
|
||||
}}
|
||||
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 noLim: boolean = false;
|
||||
switch (k)
|
||||
{
|
||||
case "Intensity":
|
||||
max = 2000;
|
||||
break;
|
||||
case "IndirectLightingIntensity":
|
||||
max = 6;
|
||||
break;
|
||||
case "Angle":
|
||||
case "InnerConeAngle":
|
||||
case "BarnDoorAngle":
|
||||
max = 90;
|
||||
break;
|
||||
case "SpecularScale":
|
||||
max = 1;
|
||||
isFloat = true;
|
||||
break;
|
||||
case "SourceLength":
|
||||
max = 1000;
|
||||
break;
|
||||
case "SourceRadius":
|
||||
case "SoftSourceRadius":
|
||||
max = 300;
|
||||
break;
|
||||
case "AttenuationRadius":
|
||||
min = 10;
|
||||
max = 1000;
|
||||
break;
|
||||
case "Width":
|
||||
case "Height":
|
||||
min = 1;
|
||||
max = 5000;
|
||||
noLim = true;
|
||||
break;
|
||||
case "BarnDoorLength":
|
||||
max = 100;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return <InputAndSlider
|
||||
pars={[k, v]}
|
||||
store={this.props.store}
|
||||
max={max}
|
||||
min={min}
|
||||
isFloat={isFloat}
|
||||
noLim={noLim}
|
||||
/>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@observer
|
||||
export class InputAndSlider extends React.Component<{ pars: string[], store: LightStore; max: number; isFloat: boolean; min: number; noLim: boolean; }, {}>
|
||||
{
|
||||
@observable _InputEl = React.createRef<NumericInput>();
|
||||
|
||||
SetValue(value: string)
|
||||
{
|
||||
const KEY = "修改灯光" + this.props.pars[1];;
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
if (app.Database.hm.UndoData.CommandName !== KEY)
|
||||
{
|
||||
app.Editor.ModalManage.EndExecingCmd().then(() =>
|
||||
{
|
||||
if (CommandState.CommandIng)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "命令正在执行中!无法修改灯光" + this.props.pars[1] + "!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commandMachine.CommandStart(KEY);
|
||||
}
|
||||
switch (this.props.pars[0])
|
||||
{
|
||||
case "InnerConeAngle":
|
||||
this.props.store.lightData.InnerConeAngle = value;
|
||||
this.props.store.currentSelectEnt[this.props.pars[0]] = parseInt(value);
|
||||
if (parseInt(value) > parseInt(this.props.store.lightData.Angle))
|
||||
{
|
||||
this.props.store.lightData.Angle = value;
|
||||
this.props.store.currentSelectEnt["Angle"] = MathUtils.degToRad(parseInt(value));
|
||||
}
|
||||
break;
|
||||
case "Angle":
|
||||
this.props.store.lightData.Angle = value;
|
||||
this.props.store.currentSelectEnt["Angle"] = MathUtils.degToRad(parseInt(value));
|
||||
if (parseInt(value) < parseInt(this.props.store.lightData.InnerConeAngle))
|
||||
{
|
||||
this.props.store.lightData.InnerConeAngle = value;
|
||||
this.props.store.currentSelectEnt["InnerConeAngle"] = parseInt(value);
|
||||
}
|
||||
break;
|
||||
case "SpecularScale":
|
||||
this.props.store.lightData.SpecularScale = value;
|
||||
this.props.store.currentSelectEnt.SpecularScale = parseFloat(value);
|
||||
break;
|
||||
default:
|
||||
this.props.store.lightData[this.props.pars[0]] = value;
|
||||
this.props.store.currentSelectEnt[this.props.pars[0]] = parseInt(value);
|
||||
break;
|
||||
}
|
||||
this.props.store.currentSelectEnt.Update();
|
||||
app.Editor.UpdateScreen();
|
||||
}
|
||||
private SyncLight()
|
||||
{
|
||||
if (userConfig.synchronousEnable)
|
||||
app.WebSocket.Send(JSON.stringify(Entitys2Data([this.props.store.currentSelectEnt])));
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<FormGroup>
|
||||
<div className='light'>
|
||||
<Label style={{ float: "left", width: 56, marginTop: 5 }}>{this.props.pars[1]}:</Label>
|
||||
<NumericInput
|
||||
min={this.props.min}
|
||||
max={this.props.noLim ? 10e6 : this.props.max}
|
||||
ref={this._InputEl}
|
||||
buttonPosition={"none"}
|
||||
value={this.props.store.lightData[this.props.pars[0]]}
|
||||
onKeyDown={(e) =>
|
||||
{
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onValueChange={(num) =>
|
||||
{
|
||||
if (isNaN(num) || num < this.props.min || num > (this.props.noLim ? 10e6 : this.props.max)) return;
|
||||
this.SetValue(FixedNotZero(num, 1));
|
||||
this.SyncLight();
|
||||
app.Viewer.UpdateRender();
|
||||
}}
|
||||
onBlur={() =>
|
||||
{
|
||||
const KEY = '修改灯光' + this.props.pars[1];;
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}}
|
||||
onFocus={(e) =>
|
||||
{
|
||||
e.target.select();
|
||||
}}
|
||||
/>
|
||||
<Slider
|
||||
min={this.props.min}
|
||||
max={this.props.max}
|
||||
stepSize={this.props.isFloat ? 0.1 : 1}
|
||||
value={parseFloat(this.props.store.lightData[this.props.pars[0]]) >= this.props.max ? this.props.max : parseFloat(this.props.store.lightData[this.props.pars[0]])}
|
||||
onChange={(e) =>
|
||||
{
|
||||
this.SetValue((FixedNotZero(e, this.props.isFloat ? 1 : 0)));
|
||||
this.SyncLight();
|
||||
app.Viewer.UpdateRender();
|
||||
}}
|
||||
onRelease={() =>
|
||||
{
|
||||
const KEY = '修改灯光' + this.props.pars[1];
|
||||
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === KEY)
|
||||
{
|
||||
commandMachine.CommandEnd();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue