Skip to content

Commit

Permalink
Fix item visibility issues + Add Sandbox B (#373)
Browse files Browse the repository at this point in the history
* Persist item visibility in reference scene

* Add sandbox scene for JBC Mat B

* Change the starting scene to JBC Sandbox A

* Remove physics impostors for invisible objects
  • Loading branch information
navzam authored Jun 15, 2022
1 parent ce7b395 commit aed83e4
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 24 deletions.
132 changes: 113 additions & 19 deletions src/SceneBinding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ class SceneBinding {
SceneBinding.apply_(ret, m => m.material = material);
}

if (node.physics) {
// Only create physics impostors for visible nodes
if (node.visible && node.physics) {
const type = IMPOSTER_TYPE_MAPPINGS[node.physics.type];
SceneBinding.apply_(ret, m => {
const currParent = m.parent;
Expand Down Expand Up @@ -722,7 +723,31 @@ class SceneBinding {

if (node.inner.visible.type === Patch.Type.OuterChange) {
const nextVisible = node.inner.visible.next;
SceneBinding.apply_(bNode, m => m.isVisible = nextVisible);
SceneBinding.apply_(bNode, m => {
m.isVisible = nextVisible;

// Remove physics impostor for object becoming invisible
if (!nextVisible && m.physicsImpostor) {
const mParent = m.parent;
m.setParent(null);
m.physicsImpostor.dispose();
m.physicsImpostor = null;
m.setParent(mParent);
}

// Create physics impostor for object becoming visible
if (nextVisible && node.next.physics) {
const type = IMPOSTER_TYPE_MAPPINGS[node.next.physics.type];
const mParent = m.parent;
m.setParent(null);
m.physicsImpostor = new Babylon.PhysicsImpostor(m, type, {
mass: node.next.physics.mass ? Mass.toGramsValue(node.next.physics.mass) : 0,
restitution: node.next.physics.restitution ?? 0.5,
friction: node.next.physics.friction ?? 5,
});
m.setParent(mParent);
}
});
}

return Promise.resolve(bNode);
Expand Down Expand Up @@ -755,33 +780,102 @@ class SceneBinding {
};

private updateFromTemplate_ = (id: string, node: Patch.InnerChange<Node.FromTemplate>, nextScene: Scene): Promise<Babylon.Node> => {
// If the template ID changes, recreate the object entirely
// If the template ID changes, recreate the node entirely
if (node.inner.templateId.type === Patch.Type.OuterChange) {
this.destroyNode_(id);
return this.createNode_(id, node.next, nextScene);
}

const bNode = this.findBNode_(id);

if (node.inner.name.type === Patch.Type.OuterChange) {
bNode.name = node.inner.name.next;
}

if (node.inner.parentId.type === Patch.Type.OuterChange) {
const parent = this.findBNode_(node.inner.parentId.next, true);
bNode.parent = parent;
}

if (node.inner.origin.type === Patch.Type.OuterChange) {
this.updateNodePosition_(node.next, bNode);
const nodeTemplate = preBuiltTemplates[node.next.templateId];
if (!nodeTemplate) {
console.warn('template node has invalid template ID:', node.next.templateId);
return Promise.resolve(bNode);
}

if (node.inner.visible.type === Patch.Type.OuterChange) {
const nextVisible = node.inner.visible.next;
SceneBinding.apply_(bNode, m => m.isVisible = nextVisible);
const prevBaseProps = Node.Base.upcast(node.prev);
const nextBaseProps = Node.Base.upcast(node.next);

// Create a Patch for the underlying node type and call its update function
switch (nodeTemplate.type) {
case 'empty': {
const emptyChange: Patch.InnerChange<Node.Empty> = {
type: Patch.Type.InnerChange,
prev: { ...nodeTemplate, ...prevBaseProps },
next: { ...nodeTemplate, ...nextBaseProps },
inner: {
...node.inner,
type: Patch.none<'empty'>('empty'),
},
};
return Promise.resolve(this.updateEmpty_(id, emptyChange));
}
case 'object': {
const objectChange: Patch.InnerChange<Node.Obj> = {
type: Patch.Type.InnerChange,
prev: { ...nodeTemplate, ...prevBaseProps },
next: { ...nodeTemplate, ...nextBaseProps },
inner: {
...node.inner,
type: Patch.none<'object'>('object'),
geometryId: Patch.none(nodeTemplate.geometryId),
physics: Patch.none(nodeTemplate.physics),
material: Patch.none(nodeTemplate.material),
faceUvs: Patch.none(nodeTemplate.faceUvs),
},
};
return this.updateObject_(id, objectChange, nextScene);
}
case 'directional-light': {
const directionalLightChange: Patch.InnerChange<Node.DirectionalLight> = {
type: Patch.Type.InnerChange,
prev: { ...nodeTemplate, ...prevBaseProps },
next: { ...nodeTemplate, ...nextBaseProps },
inner: {
...node.inner,
type: Patch.none<'directional-light'>('directional-light'),
radius: Patch.none(nodeTemplate.radius),
range: Patch.none(nodeTemplate.range),
direction: Patch.none(nodeTemplate.direction),
intensity: Patch.none(nodeTemplate.intensity),
},
};
return Promise.resolve(this.updateDirectionalLight_(id, directionalLightChange));
}
case 'spot-light': {
const spotLightChange: Patch.InnerChange<Node.SpotLight> = {
type: Patch.Type.InnerChange,
prev: { ...nodeTemplate, ...prevBaseProps },
next: { ...nodeTemplate, ...nextBaseProps },
inner: {
...node.inner,
type: Patch.none<'spot-light'>('spot-light'),
direction: Patch.none(nodeTemplate.direction),
angle: Patch.none(nodeTemplate.angle),
exponent: Patch.none(nodeTemplate.exponent),
intensity: Patch.none(nodeTemplate.intensity),
},
};
return Promise.resolve(this.updateSpotLight_(id, spotLightChange));
}
case 'point-light': {
const pointLightChange: Patch.InnerChange<Node.PointLight> = {
type: Patch.Type.InnerChange,
prev: { ...nodeTemplate, ...prevBaseProps },
next: { ...nodeTemplate, ...nextBaseProps },
inner: {
...node.inner,
type: Patch.none<'point-light'>('point-light'),
intensity: Patch.none(nodeTemplate.intensity),
radius: Patch.none(nodeTemplate.radius),
range: Patch.none(nodeTemplate.range),
},
};
return Promise.resolve(this.updatePointLight_(id, pointLightChange));
}
default: return Promise.resolve(bNode);
}

return Promise.resolve(bNode);
};

private updateNode_ = async (id: string, node: Patch<Node>, geometryPatches: Dict<Patch<Geometry>>, nextScene: Scene): Promise<Babylon.Node> => {
Expand Down
6 changes: 4 additions & 2 deletions src/components/World/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,12 @@ class World_ extends React.PureComponent<Props & ReduxWorldProps, State> {
};

private onItemVisibilityChange_ = (id: string) => (visibility: boolean) => {
const originalNode = this.props.scene.referenceScene.nodes[id];

this.props.onNodeChange(id, {
...this.props.scene.workingScene.nodes[id],
...originalNode,
visible: visibility,
}, false, false);
}, true, false);
};

render() {
Expand Down
1 change: 1 addition & 0 deletions src/scenes/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './jbcSandboxA';
export * from './jbcSandboxB';
export * from './jbc1';
export * from './jbc2';
export * from './jbc2b';
Expand Down
11 changes: 11 additions & 0 deletions src/scenes/jbcSandboxB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Scene from "../state/State/Scene";

import { createBaseSceneSurfaceB } from './jbcBase';

const baseScene = createBaseSceneSurfaceB();

export const JBC_Sandbox_B: Scene = {
...baseScene,
name: 'JBC Sandbox B',
description: `Junior Botball Challenge Sandbox on Mat B.`,
};
2 changes: 1 addition & 1 deletion src/state/State/Scene/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace Node {
visible?: boolean;
}

namespace Base {
export namespace Base {
export const NIL: Base = {
name: '',
parentId: undefined,
Expand Down
4 changes: 2 additions & 2 deletions src/state/reducer/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Geometry from "../State/Scene/Geometry";
import { ReferenceFrame } from "../../unit-math";
import Camera from "../State/Scene/Camera";

import { JBC_1 } from '../../scenes';
import { JBC_Sandbox_A } from '../../scenes';
import { ReferencedScenePair } from "..";

export namespace SceneAction {
Expand Down Expand Up @@ -212,7 +212,7 @@ export type SceneAction = (
SceneAction.SetCamera
);

export const reduceScene = (state: ReferencedScenePair = { referenceScene: JBC_1, workingScene: JBC_1 }, action: SceneAction): ReferencedScenePair => {
export const reduceScene = (state: ReferencedScenePair = { referenceScene: JBC_Sandbox_A, workingScene: JBC_Sandbox_A }, action: SceneAction): ReferencedScenePair => {
switch (action.type) {
case 'replace-scene':
return {
Expand Down
1 change: 1 addition & 0 deletions src/state/reducer/scenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export type ScenesAction = (
const DEFAULT_SCENES: Scenes = {
scenes: {
jbcSandboxA: Async.loaded({ value: JBC_SCENES.JBC_Sandbox_A }),
jbcSandboxB: Async.loaded({ value: JBC_SCENES.JBC_Sandbox_B }),
jbc1: Async.loaded({ value: JBC_SCENES.JBC_1 }),
jbc2: Async.loaded({ value: JBC_SCENES.JBC_2 }),
jbc2b: Async.loaded({ value: JBC_SCENES.JBC_2B }),
Expand Down

0 comments on commit aed83e4

Please sign in to comment.