Skip to content

Commit

Permalink
feat(controls): Add VR button to Model3D controls (#1379)
Browse files Browse the repository at this point in the history
  • Loading branch information
Conrad Chan authored May 14, 2021
1 parent 179decb commit d84e12d
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/lib/viewers/box3d/Box3D.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// For VR mode
&.vr-enabled {
// Hide this NO MATTER WHAT
.bp-ControlsRoot,
.bp-controls {
opacity: 0 !important; // stylelint-disable-line declaration-no-important
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/viewers/box3d/Box3DViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Box3DViewer extends BaseViewer {
/** @property {Notification} - Used to notify users of WebGL context issues */
contextNotification;

/** @property {boolean} - Used to show the VR button in the controls */
showVrButton = false;

/** @inheritdoc */
constructor(options) {
super(options);
Expand Down
8 changes: 6 additions & 2 deletions src/lib/viewers/box3d/model3d/Model3DControlsNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import ControlsBar from '../../controls/controls-bar';
import FullscreenToggle, { Props as FullscreenToggleProps } from '../../controls/fullscreen';
import Model3DSettings, { Props as Model3DSettingsProps } from '../../controls/model3d/Model3DSettings';
import ResetControl, { Props as ResetControlProps } from '../../controls/model3d/ResetControl';
import VrToggleControl, { Props as VrToggleControlProps } from '../../controls/model3d/VrToggleControl';

export type Props = AnimationControlsProps &
FullscreenToggleProps &
Model3DSettingsProps &
ResetControlProps & {
ResetControlProps &
VrToggleControlProps & {
onSettingsClose: () => void;
onSettingsOpen: () => void;
};
Expand All @@ -18,6 +20,7 @@ export default function Model3DControls({
cameraProjection,
currentAnimationClipId,
isPlaying,
isVrShown,
onAnimationClipSelect,
onCameraProjectionChange,
onFullscreenToggle,
Expand All @@ -30,6 +33,7 @@ export default function Model3DControls({
onShowGridToggle,
onShowSkeletonsToggle,
onShowWireframesToggle,
onVrToggle,
renderMode,
showGrid,
showSkeletons,
Expand All @@ -45,7 +49,7 @@ export default function Model3DControls({
onAnimationClipSelect={onAnimationClipSelect}
onPlayPause={onPlayPause}
/>
{/* TODO: VR button */}
<VrToggleControl isVrShown={isVrShown} onVrToggle={onVrToggle} />
<Model3DSettings
cameraProjection={cameraProjection}
onCameraProjectionChange={onCameraProjectionChange}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/viewers/box3d/model3d/Model3DViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,18 @@ class Model3DViewer extends Box3DViewer {
}
}

/**
* @inheritdoc
*/
handleShowVrButton() {
if (this.controls && this.getViewerOption('useReactControls')) {
this.showVrButton = true;
this.renderUI();
} else {
this.controls.showVrButton();
}
}

renderUI() {
if (!this.controls || !this.renderer) {
return;
Expand All @@ -478,6 +490,7 @@ class Model3DViewer extends Box3DViewer {
cameraProjection={this.projection}
currentAnimationClipId={this.renderer.getAnimationClip()}
isPlaying={this.isAnimationPlaying}
isVrShown={this.showVrButton}
onAnimationClipSelect={this.handleSelectAnimationClip}
onCameraProjectionChange={this.handleSetCameraProjection}
onFullscreenToggle={this.toggleFullscreen}
Expand All @@ -490,6 +503,7 @@ class Model3DViewer extends Box3DViewer {
onShowGridToggle={this.handleShowGrid}
onShowSkeletonsToggle={this.handleShowSkeletons}
onShowWireframesToggle={this.handleShowWireframes}
onVrToggle={this.handleToggleVr}
renderMode={this.renderMode}
showGrid={this.showGrid}
showSkeletons={this.showSkeletons}
Expand Down
22 changes: 10 additions & 12 deletions src/lib/viewers/box3d/model3d/__tests__/Model3DControlsNew-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { shallow, ShallowWrapper } from 'enzyme';
import AnimationControls from '../../../controls/model3d/AnimationControls';
import FullscreenToggle from '../../../controls/fullscreen';
import Model3DControls, { Props } from '../Model3DControlsNew';
import ResetControl from '../../../controls/model3d/ResetControl';
import Model3DSettings, { CameraProjection, RenderMode } from '../../../controls/model3d/Model3DSettings';
import ResetControl from '../../../controls/model3d/ResetControl';
import VrToggleControl from '../../../controls/model3d/VrToggleControl';

describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
const getDefaults = (): Props => ({
animationClips: [],
cameraProjection: CameraProjection.PERSPECTIVE,
currentAnimationClipId: '123',
isPlaying: false,
isVrShown: false,
onAnimationClipSelect: jest.fn(),
onCameraProjectionChange: jest.fn(),
onFullscreenToggle: jest.fn(),
Expand All @@ -24,6 +26,7 @@ describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
onShowGridToggle: jest.fn(),
onShowSkeletonsToggle: jest.fn(),
onShowWireframesToggle: jest.fn(),
onVrToggle: jest.fn(),
renderMode: RenderMode.LIT,
showGrid: true,
showSkeletons: false,
Expand All @@ -47,6 +50,7 @@ describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
const onShowGridToggle = jest.fn();
const onShowSkeletonsToggle = jest.fn();
const onShowWireframesToggle = jest.fn();
const onVrToggle = jest.fn();

const wrapper = getWrapper({
onAnimationClipSelect,
Expand All @@ -61,6 +65,7 @@ describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
onShowGridToggle,
onShowSkeletonsToggle,
onShowWireframesToggle,
onVrToggle,
});

expect(wrapper.find(ResetControl).props()).toMatchObject({
Expand All @@ -73,6 +78,10 @@ describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
onAnimationClipSelect,
onPlayPause,
});
expect(wrapper.find(VrToggleControl).props()).toMatchObject({
isVrShown: false,
onVrToggle,
});
expect(wrapper.find(Model3DSettings).props()).toMatchObject({
cameraProjection: CameraProjection.PERSPECTIVE,
onCameraProjectionChange,
Expand All @@ -91,15 +100,4 @@ describe('lib/viewers/box3d/model3d/Model3DControlsNew', () => {
expect(wrapper.find(FullscreenToggle).prop('onFullscreenToggle')).toEqual(onFullscreenToggle);
});
});

describe('onReset()', () => {
test('should call onReset prop when reset button is clicked', () => {
const onReset = jest.fn();
const wrapper = getWrapper({ onReset });

wrapper.find(ResetControl).prop('onReset')();

expect(onReset).toBeCalled();
});
});
});
15 changes: 15 additions & 0 deletions src/lib/viewers/box3d/model3d/__tests__/Model3DViewer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe('lib/viewers/box3d/model3d/Model3DViewer', () => {
on: () => {},
selectAnimationClip: () => {},
showAnimationControls: () => {},
showVrButton: () => {},
hidePullups: () => {},
removeListener: () => {},
removeAllListeners: () => {},
Expand Down Expand Up @@ -676,6 +677,11 @@ describe('lib/viewers/box3d/model3d/Model3DViewer', () => {
model3d.handleShowGrid(true);
});

test('should invoke controls.showVrButton() when calling handleShowVrButton()', () => {
sandbox.mock(model3d.controls).expects('showVrButton');
model3d.handleShowVrButton();
});

describe('with react controls', () => {
beforeEach(() => {
jest.spyOn(model3d, 'getViewerOption').mockImplementation(() => true);
Expand Down Expand Up @@ -716,6 +722,13 @@ describe('lib/viewers/box3d/model3d/Model3DViewer', () => {
expect(model3d.showGrid).toBe(false);
expect(model3d.renderUI).toBeCalled();
});

test('should update showVrButton and invoke renderUI when calling handleShowVrButton()', () => {
model3d.handleShowVrButton();

expect(model3d.showVrButton).toBe(true);
expect(model3d.renderUI).toBeCalled();
});
});
});

Expand Down Expand Up @@ -971,6 +984,7 @@ describe('lib/viewers/box3d/model3d/Model3DViewer', () => {
cameraProjection: 'Perspective',
currentAnimationClipId: '123',
isPlaying: false,
isVrShown: false,
onAnimationClipSelect: model3d.handleSelectAnimationClip,
onCameraProjectionChange: model3d.handleSetCameraProjection,
onFullscreenToggle: model3d.toggleFullscreen,
Expand All @@ -983,6 +997,7 @@ describe('lib/viewers/box3d/model3d/Model3DViewer', () => {
onShowGridToggle: model3d.handleShowGrid,
onShowSkeletonsToggle: model3d.handleShowSkeletons,
onShowWireframesToggle: model3d.handleShowWireframes,
onVrToggle: model3d.handleToggleVr,
renderMode: 'Lit',
showGrid: true,
showSkeletons: false,
Expand Down
17 changes: 17 additions & 0 deletions src/lib/viewers/controls/icons/IconVr24.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from 'react';

function IconVr24(props: React.SVGProps<SVGSVGElement>): JSX.Element {
return (
<svg focusable={false} height={24} viewBox="0 0 24 24" width={24} {...props}>
<g fill="none" fillRule="evenodd">
<path
d="M2.045 17.25c1.114 1.296 5.66 1.487 7.033.268 1.374-1.22 1.367-1.733 2.972-1.733 1.692 0 1.436-.02 3.122 1.732 1.687 1.752 5.973.84 6.9-.268.927-1.11 1.507-7.72 0-10.038-1.507-2.317-18.38-2.25-20.027 0-1.647 2.252-1.114 8.74 0 10.037z"
stroke="#FFF"
strokeWidth="2"
/>
</g>
</svg>
);
}

export default IconVr24;
5 changes: 5 additions & 0 deletions src/lib/viewers/controls/model3d/VrToggleControl.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import '../styles';

.bp-VrToggleControl {
@include bp-Control;
}
20 changes: 20 additions & 0 deletions src/lib/viewers/controls/model3d/VrToggleControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import IconVr24 from '../icons/IconVr24';
import './VrToggleControl.scss';

export type Props = {
isVrShown: boolean;
onVrToggle: () => void;
};

export default function VrToggleControl({ isVrShown, onVrToggle }: Props): JSX.Element | null {
if (!isVrShown) {
return null;
}

return (
<button className="bp-VrToggleControl" onClick={onVrToggle} title={__('box3d_toggle_vr')} type="button">
<IconVr24 />
</button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import IconVr24 from '../../icons/IconVr24';
import VrToggleControl, { Props } from '../VrToggleControl';

describe('VrToggleControl', () => {
const getDefaults = (): Props => ({
isVrShown: true,
onVrToggle: jest.fn(),
});
const getWrapper = (props = {}): ShallowWrapper => shallow(<VrToggleControl {...getDefaults()} {...props} />);

describe('render', () => {
test('should render valid wrapper', () => {
const onVrToggle = jest.fn();
const wrapper = getWrapper({ onVrToggle });

expect(wrapper.props()).toMatchObject({
className: 'bp-VrToggleControl',
onClick: onVrToggle,
title: __('box3d_toggle_vr'),
type: 'button',
});
expect(wrapper.exists(IconVr24)).toBe(true);
});

test('should render null if isVrShown is false', () => {
const wrapper = getWrapper({ isVrShown: false });

expect(wrapper.isEmptyRender()).toBe(true);
});
});
});

0 comments on commit d84e12d

Please sign in to comment.