diff --git a/ShadowEditor.Web/src/editor2/component/LightComponent.jsx b/ShadowEditor.Web/src/editor2/component/LightComponent.jsx new file mode 100644 index 00000000..b7abbee5 --- /dev/null +++ b/ShadowEditor.Web/src/editor2/component/LightComponent.jsx @@ -0,0 +1,237 @@ +import { PropertyGrid, PropertyGroup, TextProperty, DisplayProperty, CheckBoxProperty, ButtonProperty, NumberProperty, ColorProperty } from '../../third_party'; +import SetValueCommand from '../../command/SetValueCommand'; + +/** + * 光源组件 + * @author tengge / https://github.com/tengge1 + */ +class LightComponent extends React.Component { + constructor(props) { + super(props); + + this.selected = null; + + this.state = { + show: false, + expanded: true, + + showColor: false, + color: '', + + showIntensity: false, + intensity: 1.0, + + showDistance: false, + distance: 1.0, + + showAngle: false, + angle: 0.0, + + showPenumbra: false, + penumbra: 1.0, + + showDecay: false, + decay: 1.0, + + showSkyColor: false, + skyColor: '', + + showGroundColor: false, + groundColor: '', + + showWidth: false, + width: 1.0, + + showHeight: false, + height: 1.0, + }; + + this.handleExpand = this.handleExpand.bind(this); + this.handleUpdate = this.handleUpdate.bind(this); + this.handleChangeColor = this.handleChangeColor.bind(this); + this.handleChangeIntensity = this.handleChangeIntensity.bind(this); + this.handleChangeDistance = this.handleChangeDistance.bind(this); + this.handleChangeAngle = this.handleChangeAngle.bind(this); + this.handleChangePenumbra = this.handleChangePenumbra.bind(this); + this.handleChangeDecay = this.handleChangeDecay.bind(this); + this.handleChangeSkyColor = this.handleChangeSkyColor.bind(this); + this.handleChangeGroundColor = this.handleChangeGroundColor.bind(this); + this.handleChangeWidth = this.handleChangeWidth.bind(this); + this.handleChangeHeight = this.handleChangeHeight.bind(this); + } + + render() { + const { + show, expanded, + showColor, color, + showIntensity, intensity, + showDistance, distance, + showAngle, angle, + showPenumbra, penumbra, + showDecay, decay, + showSkyColor, skyColor, + showGroundColor, groundColor, + showWidth, width, + showHeight, height, + } = this.state; + + return + + + + + + + + + + + ; + } + + componentDidMount() { + app.on(`objectSelected.LightComponent`, this.handleUpdate); + app.on(`objectChanged.LightComponent`, this.handleUpdate); + } + + handleExpand(expanded) { + this.setState({ + expanded, + }); + } + + handleUpdate() { + const editor = app.editor; + + if (!editor.selected || !(editor.selected instanceof THREE.Light)) { + this.setState({ + show: false, + }); + return; + } + + this.selected = editor.selected; + + let state = this.state; + + state.show = true; + + if (this.selected instanceof THREE.HemisphereLight) { + state.showColor = false; + } else { + state.showColor = true; + state.color = `#${this.selected.color.getHexString()}`; + } + + state.showIntensity = true; + state.intensity = this.selected.intensity; + + if (this.selected instanceof THREE.PointLight || this.selected instanceof THREE.SpotLight) { + state.showDistance = true; + state.showDecay = true; + state.distance = this.selected.distance; + state.decay = this.selected.decay; + } else { + state.showDistance = false; + state.showDecay = false; + } + + if (this.selected instanceof THREE.SpotLight) { + state.showAngle = true; + state.showPenumbra = true; + state.angle = this.selected.angle; + state.penumbra = this.selected.penumbra; + } else { + state.showAngle = false; + state.showPenumbra = false; + } + + if (this.selected instanceof THREE.HemisphereLight) { + state.showSkyColor = true; + state.showGroundColor = true; + state.skyColor = `#${this.selected.color.getHexString()}`; + state.groundColor = `#${this.selected.groundColor.getHexString()}`; + } else { + state.showSkyColor = false; + state.showGroundColor = false; + } + + if (this.selected instanceof THREE.RectAreaLight) { + state.showWidth = true; + state.showHeight = true; + state.width = this.selected.width; + state.height = this.selected.height; + } else { + state.showWidth = false; + state.showHeight = false; + } + + this.setState({ state }); + } + + handleChangeColor() { + var objectColor = UI.get('objectColor', this.id); + this.selected.color = new THREE.Color(objectColor.getHexValue()); + var helper = this.selected.children.filter(n => n.userData.type === 'helper')[0]; + if (helper) { + helper.material.color = this.selected.color; + } + } + + handleChangeIntensity() { + var objectIntensity = UI.get('objectIntensity', this.id); + this.selected.intensity = objectIntensity.getValue(); + } + + handleChangeDistance() { + var objectDistance = UI.get('objectDistance', this.id); + this.selected.distance = objectDistance.getValue(); + } + + handleChangeAngle() { + var objectAngle = UI.get('objectAngle', this.id); + this.selected.angle = objectAngle.getValue(); + } + + handleChangePenumbra() { + var objectPenumbra = UI.get('objectPenumbra', this.id); + this.selected.penumbra = objectPenumbra.getValue(); + } + + handleChangeDecay() { + var objectDecay = UI.get('objectDecay', this.id); + this.selected.decay = objectDecay.getValue(); + } + + handleChangeSkyColor() { + var objectSkyColor = UI.get('objectSkyColor', this.id); + this.selected.color = new THREE.Color(objectSkyColor.getHexValue()); + + var sky = this.selected.children.filter(n => n.userData.type === 'sky')[0]; + if (sky) { + sky.material.uniforms.topColor.value = this.selected.color; + } + } + + handleChangeGroundColor() { + var objectGroundColor = UI.get('objectGroundColor', this.id); + this.selected.groundColor = new THREE.Color(objectGroundColor.getHexValue()); + + var sky = this.selected.children.filter(n => n.userData.type === 'sky')[0]; + if (sky) { + sky.material.uniforms.bottomColor.value = this.selected.groundColor; + } + } + + handleChangeWidth() { + var objectWidth = UI.get('objectWidth', this.id); + this.selected.width = objectWidth.getValue(); + } + + handleChangeHeight() { + var objectHeight = UI.get('objectHeight', this.id); + this.selected.height = objectHeight.getValue(); + } +} + +export default LightComponent; \ No newline at end of file diff --git a/ShadowEditor.Web/src/editor2/sidebar/PropertyPanel.jsx b/ShadowEditor.Web/src/editor2/sidebar/PropertyPanel.jsx index f53d0a0d..cfbb0f55 100644 --- a/ShadowEditor.Web/src/editor2/sidebar/PropertyPanel.jsx +++ b/ShadowEditor.Web/src/editor2/sidebar/PropertyPanel.jsx @@ -3,6 +3,7 @@ import { classNames, PropTypes, PropertyGrid } from '../../third_party'; import BasicComponent from '../component/BasicComponent.jsx'; import CameraComponent from '../component/CameraComponent.jsx'; import FireComponent from '../component/FireComponent.jsx'; +import LightComponent from '../component/LightComponent.jsx'; /** * 属性面板 @@ -18,6 +19,7 @@ class PropertyPanel extends React.Component { + ; } } diff --git a/ShadowEditor.Web/src/ui/form/Input.jsx b/ShadowEditor.Web/src/ui/form/Input.jsx index 74cd6cf8..5ec40ff8 100644 --- a/ShadowEditor.Web/src/ui/form/Input.jsx +++ b/ShadowEditor.Web/src/ui/form/Input.jsx @@ -59,7 +59,7 @@ Input.propTypes = { className: PropTypes.string, style: PropTypes.object, name: PropTypes.string, - type: PropTypes.oneOf(['text', 'number']), + type: PropTypes.oneOf(['text', 'number', 'color']), value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), disabled: PropTypes.bool, onChange: PropTypes.func, diff --git a/ShadowEditor.Web/src/ui/index.js b/ShadowEditor.Web/src/ui/index.js index 33e24dc1..d34db66f 100644 --- a/ShadowEditor.Web/src/ui/index.js +++ b/ShadowEditor.Web/src/ui/index.js @@ -60,6 +60,7 @@ export { default as TextProperty } from './property/TextProperty.jsx'; export { default as CheckBoxProperty } from './property/CheckBoxProperty.jsx'; export { default as NumberProperty } from './property/NumberProperty.jsx'; export { default as ButtonProperty } from './property/ButtonProperty.jsx'; +export { default as ColorProperty } from './property/ColorProperty.jsx'; // svg export { default as SVG } from './svg/SVG.jsx'; diff --git a/ShadowEditor.Web/src/ui/property/ColorProperty.jsx b/ShadowEditor.Web/src/ui/property/ColorProperty.jsx new file mode 100644 index 00000000..d69dbbfb --- /dev/null +++ b/ShadowEditor.Web/src/ui/property/ColorProperty.jsx @@ -0,0 +1,51 @@ +import './css/ColorProperty.css'; +import classNames from 'classnames/bind'; +import PropTypes from 'prop-types'; + +import Input from '../form/Input.jsx'; + +/** + * 颜色属性 + * @author tengge / https://github.com/tengge1 + */ +class ColorProperty extends React.Component { + constructor(props) { + super(props); + + this.handleChange = this.handleChange.bind(this, props.onChange); + } + + render() { + const { className, style, name, value } = this.props; + + return ; + } + + handleChange(onChange, value, name, event) { + onChange && onChange(value, name, event); + } +} + +ColorProperty.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + name: PropTypes.string, + value: PropTypes.string, + onChange: PropTypes.func, +}; + +ColorProperty.defaultProps = { + className: null, + style: null, + name: null, + value: '', + onChange: null, +}; + +export default ColorProperty; \ No newline at end of file diff --git a/ShadowEditor.Web/src/ui/property/css/ColorProperty.css b/ShadowEditor.Web/src/ui/property/css/ColorProperty.css new file mode 100644 index 00000000..aa2add3c --- /dev/null +++ b/ShadowEditor.Web/src/ui/property/css/ColorProperty.css @@ -0,0 +1,4 @@ +.ColorProperty { + width: 100%; + border: none; +} \ No newline at end of file