Skip to content

Commit

Permalink
feat(scene): move add ground plane to settings
Browse files Browse the repository at this point in the history
  • Loading branch information
haweston committed Dec 16, 2023
1 parent a6a2f3d commit 3b0c59b
Show file tree
Hide file tree
Showing 27 changed files with 695 additions and 347 deletions.
6 changes: 5 additions & 1 deletion packages/scene-composer/public/scene_1.scene.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
"far": 1000
},
"sceneBackgroundSettings": {
"color": "#0000ff"
"color": "#2a2e33"
},
"groundPlaneSettings": {
"color": "#00ff00",
"opacity": 1
}
},
"nodes": [
Expand Down
1 change: 1 addition & 0 deletions packages/scene-composer/src/SceneViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const SceneViewer: React.FC<SceneViewerProps> = ({ sceneComposerId, confi
[COMPOSER_FEATURES.Matterport]: true,
[COMPOSER_FEATURES.TagStyle]: true,
[COMPOSER_FEATURES.AutoQuery]: true,
[COMPOSER_FEATURES.SceneAppearance]: true,
},
}}
onSceneLoaded={onSceneLoaded}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports[`SceneViewer should render correctly 1`] = `
data-testid="webgl-root"
>
<div
config="{\\"mode\\":\\"Viewing\\",\\"featureConfig\\":{\\"SceneHierarchySearch\\":true,\\"SceneHierarchyReorder\\":true,\\"SubModelSelection\\":true,\\"ENHANCED_EDITING\\":true,\\"CameraView\\":true,\\"OpacityRule\\":true,\\"Overlay\\":true,\\"TagResize\\":true,\\"Matterport\\":true,\\"TagStyle\\":true,\\"AutoQuery\\":true}}"
config="{\\"mode\\":\\"Viewing\\",\\"featureConfig\\":{\\"SceneHierarchySearch\\":true,\\"SceneHierarchyReorder\\":true,\\"SubModelSelection\\":true,\\"ENHANCED_EDITING\\":true,\\"CameraView\\":true,\\"OpacityRule\\":true,\\"Overlay\\":true,\\"TagResize\\":true,\\"Matterport\\":true,\\"TagStyle\\":true,\\"AutoQuery\\":true,\\"SceneAppearance\\":true}}"
data-mocked="SceneComposerInternal"
onSceneLoaded={[Function]}
sceneComposerId="123"
Expand Down
14 changes: 3 additions & 11 deletions packages/scene-composer/src/components/WebGLCanvasManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import useMatterportViewer from '../hooks/useMatterportViewer';

import Environment, { presets } from './three-fiber/Environment';
import Fog from './three-fiber/Fog';
import GroundPlane from './three-fiber/GroundPlane';
import { StatsWindow } from './three-fiber/StatsWindow';
import EntityGroup from './three-fiber/EntityGroup';
import { EditorMainCamera } from './three-fiber/EditorCamera';
Expand Down Expand Up @@ -48,7 +49,6 @@ export const WebGLCanvasManager: React.FC = () => {
const environmentPreset = getSceneProperty<string>(KnownSceneProperty.EnvironmentPreset);
const rootNodeRefs = document.rootNodeRefs;

const editingTargetPlaneRef = useRef(null);
const gridHelperRef = useRef<THREE.GridHelper>(null);

const MAX_CLICK_DISTANCE = 2;
Expand Down Expand Up @@ -100,6 +100,7 @@ export const WebGLCanvasManager: React.FC = () => {
return node && <EntityGroup key={rootNodeRef} node={node} />;
})}
</group>
<GroundPlane />
{isEditing() && (
<React.Fragment>
<EditorTransformControls />
Expand All @@ -116,23 +117,14 @@ export const WebGLCanvasManager: React.FC = () => {
<React.Fragment>
<gridHelper
ref={gridHelperRef}
position={new THREE.Vector3(0, 0.001, 0)}
args={[
1000 /* size */,
500 /* grid# */,
hexColorFromDesignToken(awsui.colorTextInputPlaceholder) /* center line color */,
hexColorFromDesignToken(awsui.colorTextInputDisabled) /* grid color */,
]}
/>
<mesh
ref={editingTargetPlaneRef}
name='Ground'
rotation={[THREE.MathUtils.degToRad(270), 0, 0]}
onClick={onClick}
renderOrder={enableMatterportViewer ? 1 : undefined}
>
<planeGeometry args={[1000, 1000]} />
<meshBasicMaterial transparent={true} opacity={0} />
</mesh>
{enableMatterportViewer && <MatterportModel onClick={onClick} />}
</React.Fragment>
<IntlProvider locale={getGlobalSettings().locale}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { OverlayPanelVisibilityToggle } from './scene-settings/OverlayPanelVisib
import { ConvertSceneSettings } from './scene-settings/ConvertSceneSettings';
import { FogSettingsEditor } from './scene-settings/FogSettingsEditor';
import { SceneBackgroundSettingsEditor } from './scene-settings/SceneBackgroundSettingsEditor';
import { GroundPlaneSettingsEditor } from './scene-settings/GroundPlaneSettingsEditor';
export interface SettingsPanelProps {
valueDataBindingProvider?: IValueDataBindingProvider;
}
Expand Down Expand Up @@ -189,6 +190,7 @@ export const SettingsPanel: React.FC<SettingsPanelProps> = ({ valueDataBindingPr
<React.Fragment>
<FogSettingsEditor />
<SceneBackgroundSettingsEditor />
<GroundPlaneSettingsEditor />
</React.Fragment>
)}
</SpaceBetween>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ describe('PlaneGeometryComponentEditor', () => {
color: '#abcdef',
};

const componentWithTexturedGroundPlane: IPlaneGeometryComponentInternal = {
const componentWithTexturedPlane: IPlaneGeometryComponentInternal = {
...mockComponent,
type: KnownComponentType.PlaneGeometry,
width: 10,
height: 20,
textureUri: 'filepath',
isGroundPlane: true,
};

const mockFeatureConfigOn = { [COMPOSER_FEATURES.Textures]: true };
Expand Down Expand Up @@ -159,8 +158,8 @@ describe('PlaneGeometryComponentEditor', () => {
useStore('default').setState(baseState);
const { container } = render(
<PlaneGeometryComponentEditor
node={{ ...mockNode, components: [componentWithTexturedGroundPlane] }}
component={componentWithTexturedGroundPlane}
node={{ ...mockNode, components: [componentWithTexturedPlane] }}
component={componentWithTexturedPlane}
/>,
);
const polarisWrapper = wrapper(container);
Expand All @@ -174,32 +173,7 @@ describe('PlaneGeometryComponentEditor', () => {
});

expect(updateComponentInternalFn).toBeCalledTimes(1);
const { textureUri: _textureUri, ...otherComponentProps } = componentWithTexturedGroundPlane;
const { textureUri: _textureUri, ...otherComponentProps } = componentWithTexturedPlane;
expect(updateComponentInternalFn).toBeCalledWith(mockNode.ref, { ...otherComponentProps, color: '#cccccc' }, true);
});

it('should toggle ground plane status', () => {
const globalSettingsMock = getGlobalSettings as jest.Mock;
globalSettingsMock.mockReturnValue({ featureConfig: mockFeatureConfigOn });
useStore('default').setState(baseState);
const { container } = render(
<PlaneGeometryComponentEditor node={{ ...mockNode, components: [component] }} component={component} />,
);
const polarisWrapper = wrapper(container);
const groundPlaneCheckBox = polarisWrapper.findCheckbox('[data-testid="ground-plane-checkbox"]');

expect(groundPlaneCheckBox).toBeDefined();

// click checkbox should update store
act(() => {
groundPlaneCheckBox?.findNativeInput().click();
});
expect(updateComponentInternalFn).toBeCalledTimes(1);
expect(updateComponentInternalFn).toBeCalledWith(mockNode.ref, { ...component, isGroundPlane: true }, true);

act(() => {
groundPlaneCheckBox?.findNativeInput().click();
});
expect(updateComponentInternalFn).toBeCalledWith(mockNode.ref, { ...component, isGroundPlane: false }, true);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useContext, useState } from 'react';
import { Button, Checkbox, FormField, Input, SpaceBetween } from '@awsui/components-react';
import { Button, FormField, Input, SpaceBetween } from '@awsui/components-react';
import { useIntl } from 'react-intl';

import { IComponentEditorProps } from '../ComponentEditor';
Expand Down Expand Up @@ -34,7 +34,6 @@ export const PlaneGeometryComponentEditor: React.FC<IPlaneGeometryComponentEdito
const [internalHeight, setInternalHeight] = useState(planeGeometryComponent.height);
const [internalColor, setInternalColor] = useState(planeGeometryComponent.color || '#cccccc');
const [internalUri, setInternalUri] = useState(planeGeometryComponent.textureUri || '');
const [internalGroundPlane, setInternalGroundPlane] = useState(planeGeometryComponent.isGroundPlane || false);

const onUpdateCallback = useCallback(
(componentPartial: IPlaneGeometryComponentInternal, replace?: boolean) => {
Expand Down Expand Up @@ -83,17 +82,17 @@ export const PlaneGeometryComponentEditor: React.FC<IPlaneGeometryComponentEdito
const onTextureSelectClick = useCallback(() => {
if (showAssetBrowserCallback) {
showAssetBrowserCallback((s3BucketArn, contentLocation) => {
let textureUri: string;
let localTextureUri: string;
if (s3BucketArn === null) {
// This should be used for local testing only
textureUri = contentLocation;
localTextureUri = contentLocation;
} else {
textureUri = `s3://${parseS3BucketFromArn(s3BucketArn)}/${contentLocation}`;
localTextureUri = `s3://${parseS3BucketFromArn(s3BucketArn)}/${contentLocation}`;
}

setInternalUri(textureUri);
setInternalUri(localTextureUri);
const { color: _color, ...otherComponentProps } = planeGeometryComponent;
const updatedComponent = { ...otherComponentProps, textureUri };
const updatedComponent = { ...otherComponentProps, textureUri: localTextureUri };
onUpdateCallback(updatedComponent, true);
});
} else {
Expand All @@ -108,15 +107,6 @@ export const PlaneGeometryComponentEditor: React.FC<IPlaneGeometryComponentEdito
onUpdateCallback(updatedComponent, true);
}, [planeGeometryComponent, internalColor]);

const onGroundPlaneChecked = useCallback(
(checked: boolean) => {
setInternalGroundPlane(checked);
const updatedComponent = { ...planeGeometryComponent, isGroundPlane: checked };
onUpdateCallback(updatedComponent, true);
},
[planeGeometryComponent],
);

return (
<SpaceBetween size='s'>
<FormField label={intl.formatMessage({ defaultMessage: 'Width', description: 'Form Field label' })}>
Expand Down Expand Up @@ -168,13 +158,6 @@ export const PlaneGeometryComponentEditor: React.FC<IPlaneGeometryComponentEdito
<Input value={internalUri} disabled />
</SpaceBetween>
)}
<FormField label={intl.formatMessage({ defaultMessage: 'Ground Plane', description: 'Form Field label' })}>
<Checkbox
data-testid='ground-plane-checkbox'
checked={internalGroundPlane}
onChange={({ detail }) => onGroundPlaneChecked(detail.checked)}
/>
</FormField>
</SpaceBetween>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ describe('PlaneGeometryComponentEditor', () => {
color: '#abcdef',
};

const componentWithTexturedGroundPlane: IPlaneGeometryComponentInternal = {
const componentWithTexturedPlane: IPlaneGeometryComponentInternal = {
...mockComponent,
type: KnownComponentType.PlaneGeometry,
width: 10,
height: 20,
textureUri: 'filepath',
isGroundPlane: true,
};

const updateComponentInternalFn = jest.fn();
Expand Down Expand Up @@ -78,16 +77,16 @@ describe('PlaneGeometryComponentEditor', () => {
expect(container).toMatchSnapshot();
});

it('should render correctly with textured ground plane', () => {
it('should render correctly with textured plane', () => {
const globalSettingsMock = getGlobalSettings as jest.Mock;
globalSettingsMock.mockReturnValue({ featureConfig: mockFeatureConfig });

useStore('default').setState(baseState);

const { container } = render(
<PlaneGeometryComponentEditor
node={{ ...mockNode, components: [componentWithTexturedGroundPlane] }}
component={componentWithTexturedGroundPlane}
node={{ ...mockNode, components: [componentWithTexturedPlane] }}
component={componentWithTexturedPlane}
/>,
);
expect(container).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,6 @@ exports[`PlaneGeometryComponentEditor should render correctly 1`] = `
value=""
/>
</div>
<div
data-mocked="FormField"
label="Ground Plane"
>
<div
data-mocked="Checkbox"
data-testid="ground-plane-checkbox"
/>
</div>
</div>
</div>
`;
Expand Down Expand Up @@ -109,20 +100,11 @@ exports[`PlaneGeometryComponentEditor should render correctly with color 1`] = `
value=""
/>
</div>
<div
data-mocked="FormField"
label="Ground Plane"
>
<div
data-mocked="Checkbox"
data-testid="ground-plane-checkbox"
/>
</div>
</div>
</div>
`;

exports[`PlaneGeometryComponentEditor should render correctly with textured ground plane 1`] = `
exports[`PlaneGeometryComponentEditor should render correctly with textured plane 1`] = `
<div>
<div
data-mocked="SpaceBetween"
Expand Down Expand Up @@ -171,15 +153,6 @@ exports[`PlaneGeometryComponentEditor should render correctly with textured grou
value="filepath"
/>
</div>
<div
data-mocked="FormField"
label="Ground Plane"
>
<div
data-mocked="Checkbox"
data-testid="ground-plane-checkbox"
/>
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ describe('FogSettingsEditor', () => {
jest.clearAllMocks();
});

it('should save fogsettings when checked', async () => {
it('should save fogsettings when enabled', async () => {
getScenePropertyMock.mockReturnValue(undefined);
useStore('default').setState(baseState);
const { container } = render(<FogSettingsEditor />);
const polarisWrapper = wrapper(container);
const checkbox = polarisWrapper.findCheckbox();
const toggle = polarisWrapper.findToggle();

expect(checkbox).toBeDefined();
expect(toggle).toBeDefined();

// click checkbox should update store
// click should update store
act(() => {
checkbox?.findNativeInput().click();
toggle?.findNativeInput().click();
});
expect(setScenePropertyMock).toBeCalledTimes(1);
expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.FogSettings, {
Expand All @@ -44,7 +44,7 @@ describe('FogSettingsEditor', () => {
});
});

it('should clear fogsettings when unchecked', async () => {
it('should clear fogsettings when untoggled', async () => {
getScenePropertyMock.mockReturnValue({
color: '#cccccc',
near: 1,
Expand All @@ -53,13 +53,13 @@ describe('FogSettingsEditor', () => {
useStore('default').setState(baseState);
const { container } = render(<FogSettingsEditor />);
const polarisWrapper = wrapper(container);
const checkbox = polarisWrapper.findCheckbox();
const toggle = polarisWrapper.findToggle();

expect(checkbox).toBeDefined();
expect(toggle).toBeDefined();

// click checkbox should update store
// click should update store
act(() => {
checkbox?.findNativeInput().click();
toggle?.findNativeInput().click();
});
expect(setScenePropertyMock).toBeCalledTimes(1);
expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.FogSettings, undefined);
Expand Down Expand Up @@ -134,7 +134,6 @@ describe('FogSettingsEditor', () => {

expect(colorInput).toBeDefined();

// click checkbox should update store
colorInput!.focus();
colorInput!.setInputValue('#FFFFFF');
colorInput!.blur();
Expand Down

0 comments on commit 3b0c59b

Please sign in to comment.