Skip to content

Commit 0f47a5a

Browse files
authored
Merge pull request #415 from Jlu18/myr-light
New Light Features
2 parents fd84cda + 0c9b8d3 commit 0f47a5a

16 files changed

Lines changed: 1151 additions & 49 deletions

File tree

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
steps:
1616
- checkout
17-
- run:
17+
- run:
1818
name: Create firebase key file
1919
command: mkdir ~/MYR/src/keys && touch ~/MYR/src/keys/firebase.js && echo -e "export const firebaseKey = \"$FIREBASE_KEY\";\nexport default firebaseKey;" > src/keys/firebase.js
2020
# Download and cache dependencies

src/actions/sceneActions.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export function loadScene(data) {
2525
export function toggleCoordSky() {
2626
return { type: types.TOGGLE_COORD_SKY };
2727
}
28+
export function toggleDefaultLight() {
29+
return { type: types.TOGGLE_DEFAULT_LIGHT };
30+
}
31+
export function toggleCastShadow() {
32+
return { type: types.TOGGLE_CAST_SHADOW };
33+
}
34+
35+
export function toggleLightIndicator(){
36+
return {type: types.TOGGLE_LIGHT_INDICATOR};
37+
}
2838

2939
export function changeSkyColor(color) {
3040
return { type: types.CHANGE_SKY_COLOR, color };
@@ -99,5 +109,8 @@ export default {
99109
addCollectionID,
100110
setDesc,
101111
setNameDesc,
102-
removeCollectionID
112+
removeCollectionID,
113+
toggleDefaultLight,
114+
toggleCastShadow,
115+
toggleLightIndicator
103116
};

src/components/editor/customCompleter.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const customCompleter = {
4444
let keyWords = [...reference.geometry.map(obj => obj.name + "()"),
4545
...reference.transformations.map(obj => obj.name + "()"),
4646
...reference.animations.map(obj => obj.name + "()"),
47+
...reference.lights.map(obj=>obj.name+"()"),
4748
"group()"
4849
];
4950

src/components/reference/Reference.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ export default class Reference extends React.Component {
196196
</Hidden>
197197
}
198198
value='d' />
199+
<Tab
200+
icon={<Icon className="material-icons geometry">highlight</Icon>}
201+
label={
202+
<Hidden xsDown>
203+
<div>LIGHT</div>
204+
</Hidden>
205+
}
206+
value='e' />
199207
{/*<Tab
200208
style={{ background: "green", color: "white" }}
201209
icon={<Icon className="material-icons">open_in_new</Icon>}
@@ -238,6 +246,10 @@ export default class Reference extends React.Component {
238246
<div style={{ marginTop: 0, overflow: "scroll" }}>
239247
{this.TableEx("groups")}
240248
</div>}
249+
{this.state.value === "e" &&
250+
<div style={{ marginTop: 0, overflow: "scroll" }}>
251+
{this.TableEx("lights")}
252+
</div>}
241253
</Drawer>
242254
</React.Fragment> : null}
243255
</div>

src/components/reference/ReferencePage.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ export default class Reference extends React.Component {
135135
</Hidden>
136136
}
137137
value='d' />
138+
<Tab
139+
icon={<Icon className="material-icons geometry">highlights</Icon>}
140+
label={
141+
<Hidden xsDown>
142+
<div>LIGHTS</div>
143+
</Hidden>
144+
}
145+
value='e' />
138146
</Tabs>
139147
{<div style={{ margin: 5 }}>
140148
<p style={{ fontSize: "80%" }}> Key: <span className="array">array </span>
@@ -160,6 +168,10 @@ export default class Reference extends React.Component {
160168
<div style={{ marginTop: 0 }}>
161169
{this.TableEx("groups")}
162170
</div>}
171+
{this.state.value === "e" &&
172+
<div style={{ marginTop: 0 }}>
173+
{this.TableEx("lights")}
174+
</div>}
163175
</div>
164176
);
165177
}

src/components/structural/View.js

Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class View extends Component {
5959
let el = document.getElementById("rig");
6060
el.components["movement-controls"].velocity = new THREE.Vector3(0, 0, 0);
6161
}
62+
6263
}
6364

6465
componentWillUnmount() {
@@ -110,16 +111,87 @@ class View extends Component {
110111
</a-entity>
111112
);
112113
}
114+
if(ent.light){
115+
delete flattened.light;
116+
let target=null,indicator=null;
117+
if(ent.light.target){
118+
//Since the target will override the rotation, we want to delete the rotation attribute so it won't have an effect on the rotation of indicator.
119+
delete flattened.rotation;
120+
ent.light.state +="target: #lighttarget;";
121+
let target_position= `${ent.light.target.x || 0} ${ent.light.target.y || 0} ${ent.light.target.z || 0}`;
122+
target = <a-entity id="lighttarget" position={target_position}></a-entity>;
123+
}
124+
if(this.props.sceneConfig.settings.lightIndicator){
125+
indicator = this.lightIndicatorHelper(ent);
126+
}
127+
if(this.props.sceneConfig.settings.castShadow){
128+
ent.light.state += this.lightShadowHelper(ent.light);
129+
}
130+
return [<a-entity key={ent.id} id={ent.id} light={ent.light.state} {...flattened}>{indicator}</a-entity>,target];
131+
}
132+
let shadow;
133+
if(this.props.sceneConfig.settings.castShadow){
134+
shadow = "cast:true; receive:true;";
135+
}else{
136+
shadow = "cast:false; receive:false;";
137+
}
138+
113139
if (ent.text) {
114140
delete flattened.text; // this takes care of a warning, may not be necessary
115141
return <a-text key={ent.id} {...flattened}></a-text>;
116142
}
117143
if (ent.tube) {
118-
return <a-tube path={ent.path} radius={ent.radius} material={ent.material}></a-tube>;
144+
return <a-tube path={ent.path} radius={ent.radius} material={ent.material} shadow={shadow} shadowcustomsetting></a-tube>;
119145
}
120-
return <a-entity key={ent.id} {...flattened}></a-entity>;
146+
return <a-entity key={ent.id} {...flattened} shadow={shadow} shadowcustomsetting ></a-entity>;
121147
}
122148
}
149+
//return elements that contains necessary configuration for light indicator based on light's type and properties
150+
lightIndicatorHelper =(ent)=>{
151+
152+
//this is a position for passing in to indicatorroation to determine the rotation of the light that use position as vector.
153+
let position =`position:${ent.position.x || 0} ${ent.position.y || 0} ${ent.position.z || 0};`;
154+
if(ent.light.target){
155+
position += `target:${ent.light.target.x || 0} ${ent.light.target.y || 0} ${ent.light.target.z || 0};`;
156+
}
157+
158+
//ambient light doesn't have an indicator
159+
switch(ent.light.type){
160+
case "point":
161+
return <a-entity id={ent.id+"Ind"} key={ent.id+"Ind"} pointlightindicator={`color: ${ent.color};`}></a-entity>;
162+
case "spot":
163+
let target = true;
164+
if(!ent.light.target) {
165+
position = "";
166+
target = false;
167+
}
168+
return <a-entity id={ent.id+"Ind"} key={ent.id+"Ind"} spotlightindicator={`color: ${ent.color}; target:${target}`} indicatorrotation={position}></a-entity>;
169+
case "directional":
170+
return <a-entity id={ent.id+"Ind"} key={ent.id+"Ind"} directionallightindicator={`color: ${ent.color};`} indicatorrotation={position}></a-entity>;
171+
case "hemisphere":
172+
return <a-entity id={ent.id+"Ind"} key={ent.id+"Ind"} hemispherelightindicator={`color: ${ent.color}; secondColor: ${ent.light.secondColor}`}></a-entity>;
173+
default:
174+
return null;
175+
}
176+
}
177+
//return string that contains necessary configuration for shadow based on light's type
178+
lightShadowHelper = (light) =>{
179+
let newState = "";
180+
//ambient and hemisphere light doesn't cast shadow
181+
if(light.type !== "ambient" && light.type !== "hemisphere"){
182+
newState += "castShadow:true; shadowMapHeight:2000; shadowMapWidth:2000;";
183+
if(light.type === "spot"){
184+
newState += "shadowBias: -0.02; shadowCameraNear: 7;";
185+
}else if(light.type ==="directional"){
186+
newState += "shadowCameraNear: -40; shadowBias: -0.002; shadowCameraTop: 40; shadowCameraBottom: -40; shadowCameraLeft: -40; shadowCameraRight: 40;";
187+
}else if(light.type === "point"){
188+
newState += "shadowCameraFar: 25; shadowBias: -0.02;";
189+
}
190+
}else{
191+
newState += "castShadow: false;";
192+
}
193+
return newState;
194+
}
123195

124196
assetsHelper = (asset) => {
125197
return (
@@ -180,30 +252,32 @@ class View extends Component {
180252
if (this.props.sceneConfig.settings.showCoordHelper) {
181253
return (
182254
<Fragment>
183-
<a-grid height="53.33" width="53.33" position="-0.5 -0.26 -0.5" scale="1.5 1.5 1.5" />
184-
<a-tube path="-35 -0.2 0, 35 -0.2 0" radius="0.05" material="color: red"></a-tube>
185-
<a-tube path="0 -0.2 -35, 0 -0.2 35" radius="0.05" material="color: blue"></a-tube>
255+
<a-grid height="53.33" width="53.33" position="-0.5 -0.26 -0.5" scale="1.5 1.5 1.5" layer="type:mesh;layer:1;"/>
256+
<a-tube path="-35 -0.2 0, 35 -0.2 0" radius="0.05" material="color: red" layer="type:mesh;layer:1;"></a-tube>
257+
<a-tube path="0 -0.2 -35, 0 -0.2 35" radius="0.05" material="color: blue" layer="type:mesh;layer:1;"></a-tube>
186258
<a-text
187259
color="#555"
188260
rotation="0 0 0"
189261
position="-0.0005 .1 0"
190262
side="double"
191263
align="center"
192-
value="- X X +"></a-text>
264+
value="- X X +"
265+
layer="type:text;layer:1;"></a-text>
193266
<a-text
194267
color="#555"
195268
rotation="0 90 0"
196269
position="0 .1 -0.01"
197270
side="double"
198271
align="center"
199-
value="+ Z Z -">
200-
</a-text>
272+
value="+ Z Z -"
273+
layer="type:text;layer:1;"></a-text>
201274
<a-text
202275
color="#555"
203276
rotation="0 90 90"
204277
position="0 .1 0"
205278
side="double"
206-
value=" Y + "></a-text>
279+
value=" Y + "
280+
layer="type:text;layer:1;"></a-text>
207281
</Fragment>
208282
);
209283
} else {
@@ -214,12 +288,15 @@ class View extends Component {
214288
makeFloor = () => {
215289
if (this.props.sceneConfig.settings.showFloor) {
216290
return (
217-
<a-entity id="floor"
291+
<a-plane
292+
id="floor"
218293
geometry="primitive: box;"
219-
material={"color: " + this.props.sceneConfig.settings.floorColor}
294+
color={this.props.sceneConfig.settings.floorColor}
295+
material="side: double;"
220296
static-body="shape: box"
221297
scale="80 .01 80"
222298
position="0 -0.5 0"
299+
shadow={`cast: false; receive: ${this.props.sceneConfig.settings.castShadow}`}
223300
/>
224301
);
225302
} else {
@@ -231,7 +308,7 @@ class View extends Component {
231308
/* eslint-disable */
232309
return (
233310
!this.state.welcomeOpen ?
234-
<a-scene physics="debug: false; friction: 3; restitution: .3;" embedded debug="false">
311+
<a-scene scenelayer shadow="type:pcf;" physics="debug: false; friction: 3; restitution: .3;" embedded debug="false">
235312
<a-assets>
236313
<a-mixin id="checkpoint"></a-mixin>
237314
<a-mixin id="checkpoint-hovered" color="#6CEEB5"></a-mixin>
@@ -242,11 +319,25 @@ class View extends Component {
242319
<a-sky color={this.props.sceneConfig.settings.skyColor} />
243320
<this.coordinateHelper />
244321
<this.makeFloor />
322+
{this.props.sceneConfig.settings.defaultLight ?
323+
<a-entity id="DefaultLight">
324+
<a-entity id="AmbientLight" light="type: ambient; color: #BBB"></a-entity>
325+
<a-entity id="DirectionalLight" light={"type: directional; color: #FFF; intensity: 0.6; " + this.lightShadowHelper({state: "",type: "directional"})} position="-3 3 1"></a-entity>
326+
</a-entity>
327+
: null
328+
}
329+
{this.props.sceneConfig.settings.lightIndicator||this.props.sceneConfig.settings.showCoordHelper ?
330+
<a-entity id="AltLayerLight">
331+
<a-entity id="AmbientLight" light="type: ambient; color: #BBB" layer="type:light;layer:1;"></a-entity>
332+
<a-entity id="DirectionalLight" light={"type: directional; color: #FFF; intensity: 0.6; " + this.lightShadowHelper({state: "",type: "directional"})} position="-3 3 1" layer="type:light;layer:1;"></a-entity>
333+
</a-entity>
334+
: null}
245335
{ // create the entities
246336
Object.keys(this.props.objects).map(it => {
247337
return this.helper(this.props.objects[it]);
248338
})
249339
}
340+
250341

251342
{this.props.sceneConfig.settings.camConfig === 1 ?
252343
<a-entity position="0 0 0">

src/components/structural/header/SceneConfigMenu.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class ConfigModal extends Component {
9595
pwProtectOpen: false,
9696
shareOpen: false,
9797
addClassOpen: false,
98+
defaultLight: true,
99+
castShadow: false,
100+
spawnLightIndicator: false,
98101
email: "",
99102
sendTo: [],
100103
collectionID: "",
@@ -310,6 +313,66 @@ class ConfigModal extends Component {
310313
</ButtonBase >
311314
);
312315
};
316+
defaultLightToggle = () =>{
317+
let style = this.props.scene.settings.defaultLight ? btnStyle.on : btnStyle.off;
318+
style = { ...btnStyle.base, ...style };
319+
return (
320+
<ButtonBase
321+
style={style}
322+
onClick={() => {
323+
this.props.handleRender();
324+
this.props.sceneActions.toggleDefaultLight();
325+
this.setState({ settingsChanged: true });
326+
}} >
327+
{
328+
this.props.scene.settings.defaultLight
329+
? <Icon className="material-icons">toggle_on</Icon>
330+
: <Icon className="material-icons">toggle_off</Icon>
331+
}
332+
Default Light
333+
</ButtonBase >
334+
);
335+
}
336+
castShadowToggle = () => {
337+
let style = this.props.scene.settings.castShadow ? btnStyle.on : btnStyle.off;
338+
style = { ...btnStyle.base, ...style };
339+
return (
340+
<ButtonBase
341+
style={style}
342+
onClick={() => {
343+
this.props.handleRender();
344+
this.props.sceneActions.toggleCastShadow();
345+
this.setState({ settingsChanged: true });
346+
}} >
347+
{
348+
this.props.scene.settings.castShadow
349+
? <Icon className="material-icons">toggle_on</Icon>
350+
: <Icon className="material-icons">toggle_off</Icon>
351+
}
352+
Cast Shadow
353+
</ButtonBase >
354+
);
355+
}
356+
lightIndicatorToggle = () => {
357+
let style = this.props.scene.settings.lightIndicator ? btnStyle.on : btnStyle.off;
358+
style = { ...btnStyle.base, ...style };
359+
return (
360+
<ButtonBase
361+
style={style}
362+
onClick={() => {
363+
this.props.handleRender();
364+
this.props.sceneActions.toggleLightIndicator();
365+
this.setState({ settingsChanged: true });
366+
}} >
367+
{
368+
this.props.scene.settings.lightIndicator
369+
? <Icon className="material-icons">toggle_on</Icon>
370+
: <Icon className="material-icons">toggle_off</Icon>
371+
}
372+
Light Indicator
373+
</ButtonBase >
374+
);
375+
}
313376

314377
/**
315378
* Toggles the floor on and off
@@ -492,6 +555,14 @@ class ConfigModal extends Component {
492555
<this.changeSkyColor />
493556
<this.changeFloorColor />
494557
</div>
558+
<div className="col-12 border-bottom pt-4">Light Control</div>
559+
<div className="col-6">
560+
<this.defaultLightToggle/>
561+
<this.castShadowToggle/>
562+
</div>
563+
<div className="col-6">
564+
<this.lightIndicatorToggle/>
565+
</div>
495566
<div className="col-12 border-bottom pt-4">Camera Control</div>
496567
<div className="col-6">
497568
<this.flyToggle />

src/constants/ActionTypes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ export const ADD_CLASSROOM = "ADD_CLASSROOM";
4141
export const REMOVE_CLASSROOM = "REMOVE_CLASSROOM";
4242
export const SET_DESC = "SET_DESC";
4343
export const SET_NAME_DESC = "SET_NAME_DESC";
44+
export const TOGGLE_DEFAULT_LIGHT = "TOGGLE_DEFAULT_LIGHT";
45+
export const TOGGLE_CAST_SHADOW = "TOGGLE_CAST_SHADOW";
46+
export const TOGGLE_LIGHT_INDICATOR = "TOGGLE_LIGHT_INDICATOR";
4447

4548
export const SYNC_CLASSES = "SYNC_CLASSES";
4649
export const SYNC_CLASS = "SYNC_CLASS";

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import ReactDOM from "react-dom";
33
import { Provider } from "react-redux";
44
import "./utils/AframeReg";
5+
import "./utils/AframeRegIndicator";
56
import "bootstrap/dist/css/bootstrap.css";
67
import "./css/App.css";
78

0 commit comments

Comments
 (0)