diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/AnchorWidget.tsx b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/AnchorWidget.tsx
index 0d9997f73..a6390c600 100644
--- a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/AnchorWidget.tsx
+++ b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/AnchorWidget.tsx
@@ -15,6 +15,7 @@ import {
DefaultAnchorStatus,
INavLink,
IRuleBasedMap,
+ ITagSettings,
IValueDataBinding,
KnownComponentType,
SceneResourceType,
@@ -28,6 +29,7 @@ import { getSceneResourceInfo } from '../../../../utils/sceneResourceUtils';
import svgIconToWidgetSprite from '../common/SvgIconToWidgetSprite';
import { findComponentByType } from '../../../../utils/nodeUtils';
import { Layers } from '../../../../common/constants';
+import { componentSettingsSelector } from '../../../../utils/componentSettingsUtils';
export interface AnchorWidgetProps {
node: ISceneNodeInternal;
@@ -59,6 +61,12 @@ export function AsyncLoadedAnchorWidget({
dataBindingTemplate,
} = useStore(sceneComposerId)((state) => state);
const isViewing = useStore(sceneComposerId)((state) => state.isViewing());
+ const tagSettings: ITagSettings = useStore(sceneComposerId)((state) =>
+ componentSettingsSelector(state, KnownComponentType.Tag),
+ );
+ const autoRescale = useMemo(() => {
+ return tagSettings.autoRescale;
+ }, [tagSettings.autoRescale]);
const onWidgetClick = useStore(sceneComposerId)((state) => state.getEditorConfig().onWidgetClick);
const getObject3DFromSceneNodeRef = useStore(sceneComposerId)((state) => state.getObject3DBySceneNodeRef);
@@ -77,8 +85,11 @@ export function AsyncLoadedAnchorWidget({
const baseScale = useMemo(() => {
// NOTE: For Fixed Size value was [0.05, 0.05, 1]
- return new THREE.Vector3(0.5, 0.5, 1).multiply(new THREE.Vector3(...node.transform.scale));
- }, [node.transform.scale]);
+ const defaultScale = autoRescale ? [0.05, 0.05, 1] : [0.5, 0.5, 1];
+ return new THREE.Vector3(...defaultScale).multiply(
+ new THREE.Vector3(tagSettings.scale, tagSettings.scale, tagSettings.scale),
+ );
+ }, [autoRescale, tagSettings.scale]);
useEffect(() => {
setParent(node.parentRef ? getObject3DFromSceneNodeRef(node.parentRef) : undefined);
@@ -115,9 +126,9 @@ export function AsyncLoadedAnchorWidget({
VideoIconSvgString,
];
return iconStrings.map((iconString, index) => {
- return svgIconToWidgetSprite(iconString, keys[index], isAlwaysVisible);
+ return svgIconToWidgetSprite(iconString, keys[index], isAlwaysVisible, !autoRescale);
});
- }, []);
+ }, [autoRescale]);
const isAnchor = (nodeRef?: string) => {
const node = getSceneNodeByRef(nodeRef);
diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx
index 22f0925aa..62d22ac81 100644
--- a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx
+++ b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/AnchorWidget.spec.tsx
@@ -27,6 +27,7 @@ describe('AnchorWidget', () => {
const setHighlightedSceneNodeRef = jest.fn();
const setSelectedSceneNodeRef = jest.fn();
const getObject3DBySceneNodeRef = jest.fn();
+ const getSceneProperty = jest.fn();
const node = {
ref: 'test-ref',
@@ -51,11 +52,13 @@ describe('AnchorWidget', () => {
getEditorConfig: () => ({ onWidgetClick }),
dataInput: 'dataInput' as any,
getObject3DBySceneNodeRef,
+ getSceneProperty,
} as any);
};
beforeEach(() => {
(useLoader as unknown as jest.Mock).mockReturnValue(['TestSvgData']);
+ getSceneProperty.mockReturnValue(undefined);
jest.clearAllMocks();
});
@@ -93,6 +96,14 @@ describe('AnchorWidget', () => {
expect(container).toMatchSnapshot();
});
+ it('should render correctly with non default tag settings', () => {
+ setStore('test-ref', 'test-ref');
+ getSceneProperty.mockReturnValue({ Tag: { scale: 3, autoRescale: true } });
+ const container = renderer.create();
+
+ expect(container).toMatchSnapshot();
+ });
+
it('should render correctly with an offset', () => {
setStore('test-ref', 'test-ref');
const node = {
diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap
index b699006b4..fe3a04b3b 100644
--- a/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap
+++ b/packages/scene-composer/src/augmentations/components/three-fiber/anchor/__tests__/__snapshots__/AnchorWidget.spec.tsx.snap
@@ -116,6 +116,64 @@ exports[`AnchorWidget should render correctly with an offset 1`] = `
`;
+exports[`AnchorWidget should render correctly with non default tag settings 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
exports[`AnchorWidget should render with a countered size when parent is scaled 1`] = `
{
+ const icons = [
+ ['Selected', { key: SelectedAnchor, icon: SelectedIconSvgString }],
+ ['Info', { key: DefaultAnchorStatus.Info, icon: InfoIconSvgString }],
+ ['Warning', { key: DefaultAnchorStatus.Warning, icon: WarningIconSvgString }],
+ ['Error', { key: DefaultAnchorStatus.Error, icon: ErrorIconSvgString }],
+ ['Video', { key: DefaultAnchorStatus.Video, icon: VideoIconSvgString }],
+ ];
+
+ icons.forEach((value) => {
+ it(`it should render the ${value[0]} correctly`, () => {
+ jest.spyOn(window.Math, 'random').mockReturnValue(0.1);
+ const { key, icon } = value[1] as any;
+ const container = renderer.create(svgIconToWidgetSprite(icon, key, false, true));
+
+ expect(container).toMatchSnapshot();
+ });
+ });
+
+ icons.forEach((value) => {
+ it(`it should render the always visible ${value[0]} correctly`, () => {
+ jest.spyOn(window.Math, 'random').mockReturnValue(0.1);
+ const { key, icon } = value[1] as any;
+ const container = renderer.create(svgIconToWidgetSprite(icon, key, true, true));
+
+ expect(container).toMatchSnapshot();
+ });
+ });
+
+ icons.forEach((value) => {
+ it(`it should render the constant sized ${value[0]} correctly`, () => {
+ jest.spyOn(window.Math, 'random').mockReturnValue(0.1);
+ const { key, icon } = value[1] as any;
+ const container = renderer.create(svgIconToWidgetSprite(icon, key, false, false));
+
+ expect(container).toMatchSnapshot();
+ });
+ });
+});
diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.tsx b/packages/scene-composer/src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.tsx
index 31f426a59..0a7128657 100644
--- a/packages/scene-composer/src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.tsx
+++ b/packages/scene-composer/src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.tsx
@@ -9,6 +9,7 @@ export default function svgIconToWidgetSprite(
svg: string,
key: DefaultAnchorStatus | string,
alwaysVisible,
+ sizeAttenuation: boolean, // when true, tag size changes when zooming
props?: WidgetSpriteProps,
) {
if (!THREE.Cache.get(key)) {
@@ -21,29 +22,30 @@ export default function svgIconToWidgetSprite(
THREE.Cache.add(key, texture);
}
- const group = new THREE.Group();
-
const texture = THREE.Cache.get(key);
- // NOTE: sizeAttenuation is true by default, but I am leaving this as setting it to false is what maintains a constant size.
- const spriteMaterial = new THREE.SpriteMaterial({ map: texture, sizeAttenuation: true });
- spriteMaterial.color.convertSRGBToLinear();
- const sprite = new THREE.Sprite(spriteMaterial);
- sprite.renderOrder = RenderOrder.DrawLate;
-
- group.add(sprite);
-
- if (alwaysVisible) {
- const altSpriteMaterial = spriteMaterial.clone();
- altSpriteMaterial.depthFunc = THREE.GreaterDepth;
- altSpriteMaterial.opacity = 0.5;
- const altSprite = new THREE.Sprite(altSpriteMaterial);
- altSprite.renderOrder = RenderOrder.DrawLate;
- group.add(altSprite);
- }
return (
-
+
+
+
+
+ {alwaysVisible && (
+
+
+
+ )}
+
);
}
diff --git a/packages/scene-composer/src/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap b/packages/scene-composer/src/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap
new file mode 100644
index 000000000..921335e51
--- /dev/null
+++ b/packages/scene-composer/src/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap
@@ -0,0 +1,316 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`svgIconToWidgetSprite it should render the Error correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the Info correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the Selected correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the Video correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the Warning correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the always visible Error correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the always visible Info correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the always visible Selected correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the always visible Video correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the always visible Warning correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the constant sized Error correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the constant sized Info correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the constant sized Selected correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the constant sized Video correctly 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`svgIconToWidgetSprite it should render the constant sized Warning correctly 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/packages/scene-composer/src/common/constants.ts b/packages/scene-composer/src/common/constants.ts
index fe6b478ed..06f6a78b0 100644
--- a/packages/scene-composer/src/common/constants.ts
+++ b/packages/scene-composer/src/common/constants.ts
@@ -2,7 +2,13 @@ import * as THREE from 'three';
import { Component, LightType } from '../models/SceneModels';
import { InfoIconSvgString, WarningIconSvgString, ErrorIconSvgString, VideoIconSvgString } from '../assets';
-import { IValueDataBindingProviderState, DefaultAnchorStatus, DistanceUnit, Vector3 } from '../interfaces';
+import {
+ IValueDataBindingProviderState,
+ DefaultAnchorStatus,
+ DistanceUnit,
+ Vector3,
+ ITagSettings,
+} from '../interfaces';
import { CameraControlImpl } from '../store/internalInterfaces';
/******************************************************************************
@@ -115,6 +121,11 @@ export const SCENE_BODY_CLASS = 'twinmaker_scene_container';
export const DRACO_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/';
+export const DEFAULT_TAG_GLOBAL_SETTINGS: ITagSettings = {
+ autoRescale: false,
+ scale: 1,
+};
+
/******************************************************************************
* Camera Constants
******************************************************************************/
diff --git a/packages/scene-composer/src/components/panels/SceneNodeInspectorPanel.tsx b/packages/scene-composer/src/components/panels/SceneNodeInspectorPanel.tsx
index 9eae49e01..8cd796e07 100644
--- a/packages/scene-composer/src/components/panels/SceneNodeInspectorPanel.tsx
+++ b/packages/scene-composer/src/components/panels/SceneNodeInspectorPanel.tsx
@@ -28,7 +28,6 @@ export const SceneNodeInspectorPanel: React.FC = () => {
const selectedSceneNode = getSceneNodeByRef(selectedSceneNodeRef);
const intl = useIntl();
- const tagResizeEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.TagResize];
const subModelMovementEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.SubModelMovement];
const i18nKnownComponentTypesStrings = defineMessages({
@@ -89,7 +88,7 @@ export const SceneNodeInspectorPanel: React.FC = () => {
const transformVisible = !isSubModelComponent || subModelMovementEnabled;
- const shouldShowScale = !((isTagComponent && !tagResizeEnabled) || isCameraComponent);
+ const shouldShowScale = !(isTagComponent || isCameraComponent);
const readonly: Triplet = [false, false, false];
diff --git a/packages/scene-composer/src/components/panels/SettingsPanel.tsx b/packages/scene-composer/src/components/panels/SettingsPanel.tsx
index 105bd2975..557f62b95 100644
--- a/packages/scene-composer/src/components/panels/SettingsPanel.tsx
+++ b/packages/scene-composer/src/components/panels/SettingsPanel.tsx
@@ -6,11 +6,12 @@ import useLifecycleLogging from '../../logger/react-logger/hooks/useLifecycleLog
import { presets } from '../three-fiber/Environment';
import { sceneComposerIdContext } from '../../common/sceneComposerIdContext';
import { useStore } from '../../store';
-import { IValueDataBindingProvider, KnownSceneProperty } from '../../interfaces';
+import { COMPOSER_FEATURES, IValueDataBindingProvider, KnownSceneProperty } from '../../interfaces';
import { pascalCase } from '../../utils/stringUtils';
+import { getGlobalSettings } from '../../common/GlobalSettings';
import { ExpandableInfoSection } from './CommonPanelComponents';
-import { SceneDataBindingTemplateEditor } from './scene-settings';
+import { SceneDataBindingTemplateEditor, SceneTagSettingsEditor } from './scene-settings';
export interface SettingsPanelProps {
valueDataBindingProvider?: IValueDataBindingProvider;
@@ -22,6 +23,8 @@ export const SettingsPanel: React.FC = ({ valueDataBindingPr
const setSceneProperty = useStore(sceneComposerId)((state) => state.setSceneProperty);
const intl = useIntl();
+ const tagResizeEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.TagResize];
+
const selectedEnvPreset = useStore(sceneComposerId)((state) =>
state.getSceneProperty(KnownSceneProperty.EnvironmentPreset),
);
@@ -92,6 +95,16 @@ export const SettingsPanel: React.FC = ({ valueDataBindingPr
+
+ {tagResizeEnabled && (
+
+
+
+ )}
+
{valueDataBindingProvider && (
, HTMLInputElement> {}
diff --git a/packages/scene-composer/tests/components/panels/SettingsPanel.spec.tsx b/packages/scene-composer/src/components/panels/__tests__/SettingsPanel.spec.tsx
similarity index 56%
rename from packages/scene-composer/tests/components/panels/SettingsPanel.spec.tsx
rename to packages/scene-composer/src/components/panels/__tests__/SettingsPanel.spec.tsx
index badcf9cd2..b92d50503 100644
--- a/packages/scene-composer/tests/components/panels/SettingsPanel.spec.tsx
+++ b/packages/scene-composer/src/components/panels/__tests__/SettingsPanel.spec.tsx
@@ -4,9 +4,11 @@ import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { Select } from '@awsui/components-react';
-import { SettingsPanel } from '../../../src/components/panels';
-import { ExpandableInfoSection } from '../../../src/components/panels/CommonPanelComponents';
-import { useStore } from '../../../src/store';
+import { SettingsPanel } from '..';
+import { ExpandableInfoSection } from '../CommonPanelComponents';
+import { useStore } from '../../../store';
+import { setFeatureConfig } from '../../../common/GlobalSettings';
+import { COMPOSER_FEATURES } from '../../../interfaces';
jest.spyOn(React, 'useContext').mockReturnValue('sceneComponserId' as any);
@@ -22,7 +24,8 @@ describe('SettingsPanel contains expected elements.', () => {
const wrapper = shallow();
const expandableInfoSection = wrapper.find(ExpandableInfoSection);
- expect(expandableInfoSection.props().title).toEqual('Scene Settings');
+ expect(expandableInfoSection.length).toEqual(1);
+ expect(expandableInfoSection.at(0).props().title).toEqual('Scene Settings');
const selectProps = expandableInfoSection.find(Select).props();
@@ -41,4 +44,20 @@ describe('SettingsPanel contains expected elements.', () => {
expect(setSceneProperty.mock.calls[0][1]).toEqual(undefined);
setSceneProperty.mockReset();
});
+
+ it('SettingsPanel contains tag settings element.', async () => {
+ setFeatureConfig({ [COMPOSER_FEATURES.TagResize]: true });
+ const setSceneProperty = jest.fn();
+ useStore('sceneComponserId').setState({
+ setSceneProperty: setSceneProperty,
+ getSceneProperty: jest.fn().mockReturnValue('neutral'),
+ });
+
+ const wrapper = shallow();
+
+ const expandableInfoSections = wrapper.find(ExpandableInfoSection);
+ expect(expandableInfoSections.length).toEqual(2);
+ expect(expandableInfoSections.at(0).props().title).toEqual('Scene Settings');
+ expect(expandableInfoSections.at(1).props().title).toEqual('Tag Settings');
+ });
});
diff --git a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/Slider.spec.tsx b/packages/scene-composer/src/components/panels/__tests__/Slider.spec.tsx
similarity index 86%
rename from packages/scene-composer/tests/components/panels/scene-components/motion-indicator/Slider.spec.tsx
rename to packages/scene-composer/src/components/panels/__tests__/Slider.spec.tsx
index 6377dd222..da01cf8c6 100644
--- a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/Slider.spec.tsx
+++ b/packages/scene-composer/src/components/panels/__tests__/Slider.spec.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
-import { Slider } from '../../../../../src/components/panels/scene-components/motion-indicator/Slider';
+import { Slider } from '../Slider';
describe('Slider', () => {
it('should render correctly', () => {
diff --git a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/__snapshots__/Slider.spec.tsx.snap b/packages/scene-composer/src/components/panels/__tests__/__snapshots__/Slider.spec.tsx.snap
similarity index 100%
rename from packages/scene-composer/tests/components/panels/scene-components/motion-indicator/__snapshots__/Slider.spec.tsx.snap
rename to packages/scene-composer/src/components/panels/__tests__/__snapshots__/Slider.spec.tsx.snap
diff --git a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.spec.tsx b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.spec.tsx
index 3ccde93ee..683a1a7d3 100644
--- a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.spec.tsx
+++ b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.spec.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
-import wrapper from '@awsui/components-react/test-utils/dom';
import { mockComponent, mockProvider } from '../../../../../tests/components/panels/scene-components/MockComponents';
import { IMotionIndicatorComponentInternal, useStore } from '../../../../store';
@@ -18,8 +17,8 @@ jest.mock('./DataBindingEditor', () => {
});
let sliderOnChangeCb;
-jest.mock('./Slider', () => {
- const originalModule = jest.requireActual('./Slider');
+jest.mock('../../Slider', () => {
+ const originalModule = jest.requireActual('../../Slider');
return {
...originalModule,
Slider: (...props: any[]) => {
diff --git a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.tsx b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.tsx
index c7e3140fe..e7db64a1c 100644
--- a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.tsx
+++ b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/ColorEditor.tsx
@@ -9,9 +9,9 @@ import { IMotionIndicatorComponentInternal, useStore } from '../../../../store';
import { sceneComposerIdContext } from '../../../../common/sceneComposerIdContext';
import { Component } from '../../../../models/SceneModels';
import { colors } from '../../../../utils/styleUtils';
+import { Slider } from '../../Slider';
import { DataBindingEditor } from './DataBindingEditor';
-import { Slider } from './Slider';
const ColorSwatch = styled.div<{ backgroundColor: string }>`
background-color: ${(props) => props.backgroundColor};
diff --git a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/SpeedEditor.tsx b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/SpeedEditor.tsx
index e908eac2b..f5991b1e5 100644
--- a/packages/scene-composer/src/components/panels/scene-components/motion-indicator/SpeedEditor.tsx
+++ b/packages/scene-composer/src/components/panels/scene-components/motion-indicator/SpeedEditor.tsx
@@ -6,9 +6,9 @@ import { useIntl } from 'react-intl';
import { IMotionIndicatorComponentInternal, useStore } from '../../../../store';
import { sceneComposerIdContext } from '../../../../common/sceneComposerIdContext';
import { Component } from '../../../../models/SceneModels';
+import { Slider } from '../../Slider';
import { DataBindingEditor } from './DataBindingEditor';
-import { Slider } from './Slider';
interface ISpeedEditorProps {
component: IMotionIndicatorComponentInternal;
diff --git a/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.spec.tsx b/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.spec.tsx
new file mode 100644
index 000000000..c96052f80
--- /dev/null
+++ b/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.spec.tsx
@@ -0,0 +1,135 @@
+/* eslint-disable import/first */
+import React from 'react';
+import { act, fireEvent, render, screen } from '@testing-library/react';
+import wrapper from '@awsui/components-react/test-utils/dom';
+
+import { useStore } from '../../../store';
+import { KnownComponentType, KnownSceneProperty } from '../../../interfaces';
+import { DEFAULT_TAG_GLOBAL_SETTINGS } from '../../../common/constants';
+
+import { SceneTagSettingsEditor } from './SceneTagSettingsEditor';
+
+jest.mock('@awsui/components-react', () => ({
+ ...jest.requireActual('@awsui/components-react'),
+}));
+
+const sleep = async (timeout: number) => {
+ return new Promise((resolve) => setTimeout(resolve, timeout));
+};
+
+describe('SceneTagSettingsEditor', () => {
+ const setScenePropertyMock = jest.fn();
+ const getScenePropertyMock = jest.fn();
+ const baseState = {
+ setSceneProperty: setScenePropertyMock,
+ getSceneProperty: getScenePropertyMock,
+ };
+
+ beforeEach(() => {
+ jest.useRealTimers();
+ getScenePropertyMock.mockReturnValue({
+ [KnownComponentType.Tag]: DEFAULT_TAG_GLOBAL_SETTINGS,
+ });
+ jest.clearAllMocks();
+ });
+
+ it('should update store when input value changed', async () => {
+ useStore('default').setState(baseState);
+ const { container } = render();
+ const polarisWrapper = wrapper(container);
+ const input = polarisWrapper.findInput();
+
+ expect(input).toBeDefined();
+
+ // change input should update store when value is valid
+ input?.setInputValue('11');
+ expect(setScenePropertyMock).toBeCalledTimes(1);
+ expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.ComponentSettings, {
+ [KnownComponentType.Tag]: { ...DEFAULT_TAG_GLOBAL_SETTINGS, scale: 11 },
+ });
+
+ // change input should update store with 0 when value is invalid
+ input?.setInputValue('-11');
+ expect(setScenePropertyMock).toBeCalledTimes(2);
+ expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.ComponentSettings, {
+ [KnownComponentType.Tag]: { ...DEFAULT_TAG_GLOBAL_SETTINGS, scale: 0 },
+ });
+ });
+
+ it('should update input value when store value changed', async () => {
+ useStore('default').setState(baseState);
+ const { container } = render();
+ const polarisWrapper = wrapper(container);
+ const input = polarisWrapper.findInput();
+
+ expect(input).toBeDefined();
+ expect(input?.findNativeInput().getElement().value).toEqual(String(DEFAULT_TAG_GLOBAL_SETTINGS.scale));
+
+ getScenePropertyMock.mockReturnValue({
+ [KnownComponentType.Tag]: { ...DEFAULT_TAG_GLOBAL_SETTINGS, scale: 6 },
+ });
+ act(() => {
+ useStore('default').setState({ ...baseState });
+ });
+
+ expect(polarisWrapper.findInput()?.findNativeInput().getElement().value).toEqual('6');
+ });
+
+ it('should update store when checkbox clicked', async () => {
+ useStore('default').setState(baseState);
+ const { container } = render();
+ const polarisWrapper = wrapper(container);
+ const checkbox = polarisWrapper.findCheckbox();
+
+ expect(checkbox).toBeDefined();
+
+ // click checkbox should update store
+ checkbox?.findNativeInput().click();
+ expect(setScenePropertyMock).toBeCalledTimes(1);
+ expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.ComponentSettings, {
+ [KnownComponentType.Tag]: {
+ ...DEFAULT_TAG_GLOBAL_SETTINGS,
+ autoRescale: !DEFAULT_TAG_GLOBAL_SETTINGS.autoRescale,
+ },
+ });
+ });
+
+ it('should update store when slider value changed', async () => {
+ useStore('default').setState(baseState);
+ const { container } = render();
+ const polarisWrapper = wrapper(container);
+
+ // slider is hidden initially
+ expect(screen.queryAllByTestId('slider').length).toBe(0);
+
+ // show slider when input gets focus
+ const input = polarisWrapper.findInput();
+ act(() => {
+ input?.focus();
+ });
+ const slider = screen.queryAllByTestId('slider');
+ expect(slider.length).toBe(1);
+
+ await act(async () => {
+ slider[0].focus();
+
+ input?.blur();
+ // wait for setTimeOut in code
+ await sleep(2);
+
+ // update slider value should update store
+ fireEvent.change(slider[0], { target: { value: '3' } });
+ });
+
+ expect(setScenePropertyMock).toBeCalledTimes(1);
+ expect(setScenePropertyMock).toBeCalledWith(KnownSceneProperty.ComponentSettings, {
+ [KnownComponentType.Tag]: { ...DEFAULT_TAG_GLOBAL_SETTINGS, scale: 3 },
+ });
+
+ // hide slider when slider lost focus
+ act(() => {
+ slider[0].blur();
+ });
+ expect(screen.queryAllByTestId('slider').length).toBe(0);
+ });
+});
diff --git a/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.tsx b/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.tsx
new file mode 100644
index 000000000..0bc054abb
--- /dev/null
+++ b/packages/scene-composer/src/components/panels/scene-settings/SceneTagSettingsEditor.tsx
@@ -0,0 +1,136 @@
+import React, { useCallback, useContext, useEffect, useState } from 'react';
+import { useIntl } from 'react-intl';
+import { Checkbox, FormField, Grid, Input } from '@awsui/components-react';
+
+import useLifecycleLogging from '../../../logger/react-logger/hooks/useLifecycleLogging';
+import { useStore } from '../../../store';
+import { sceneComposerIdContext } from '../../../common/sceneComposerIdContext';
+import { IComponentSettingsMap, ITagSettings, KnownComponentType, KnownSceneProperty } from '../../../interfaces';
+import { componentSettingsSelector } from '../../../utils/componentSettingsUtils';
+import { Slider } from '../Slider';
+
+export const SceneTagSettingsEditor: React.FC = () => {
+ useLifecycleLogging('SceneTagSettingsEditor');
+
+ const sceneComposerId = useContext(sceneComposerIdContext);
+ const intl = useIntl();
+ const setSceneProperty = useStore(sceneComposerId)((state) => state.setSceneProperty);
+ const getSceneProperty = useStore(sceneComposerId)((state) => state.getSceneProperty);
+ const tagSettings: ITagSettings = useStore(sceneComposerId)((state) =>
+ componentSettingsSelector(state, KnownComponentType.Tag),
+ );
+ const [dirty, setDirty] = useState(false);
+ const [focusInput, setFocusInput] = useState(false);
+ const [focusSlider, setFocusSlider] = useState(false);
+ const [draggingSlider, setDraggingSlider] = useState(false);
+
+ const [internalScale, setInternalScale] = useState(tagSettings.scale);
+
+ const updateSettings = useCallback(
+ (settingsPartial: Partial) => {
+ const newTagSettings: ITagSettings = {
+ ...tagSettings,
+ ...settingsPartial,
+ };
+ const newComponentSettings: IComponentSettingsMap = {
+ ...getSceneProperty(KnownSceneProperty.ComponentSettings),
+ [KnownComponentType.Tag]: newTagSettings,
+ };
+
+ setSceneProperty(KnownSceneProperty.ComponentSettings, newComponentSettings);
+ },
+ [tagSettings, getSceneProperty, setSceneProperty],
+ );
+
+ const onSliderChange = useCallback(
+ (event) => {
+ setInternalScale(Number(event.target.value));
+ setDirty(true);
+ },
+ [setInternalScale, setDirty],
+ );
+
+ const onInputBlur = useCallback(() => {
+ // If slider is getting focus, this makes sure to execute setFocusSlider(true) first to keep showing it.
+ const id = setTimeout(() => {
+ setFocusInput(false);
+ }, 1);
+ return () => {
+ clearTimeout(id);
+ };
+ }, [setFocusInput]);
+
+ const onInputChange = useCallback(
+ (event) => {
+ let value = event.detail.value;
+ if (value < 0) {
+ value = 0;
+ }
+
+ if (value !== internalScale) {
+ setInternalScale(Number(value));
+ setDirty(true);
+ }
+ },
+ [setInternalScale, setDirty],
+ );
+
+ // Save scale changes to scene file
+ useEffect(() => {
+ if (dirty && !focusInput && !draggingSlider) {
+ updateSettings({ scale: internalScale });
+ setDirty(false);
+ }
+ }, [updateSettings, setDirty, dirty, focusInput, internalScale, draggingSlider]);
+
+ // Update internal when scale in store is changed
+ useEffect(() => {
+ if (!dirty && tagSettings.scale !== internalScale) {
+ setInternalScale(tagSettings.scale);
+ }
+ }, [dirty, draggingSlider, tagSettings.scale, internalScale]);
+
+ return (
+
+
+
+ setFocusInput(true)}
+ onBlur={onInputBlur}
+ onChange={onInputChange}
+ />
+ updateSettings({ autoRescale: e.detail.checked })}
+ >
+ {intl.formatMessage({ defaultMessage: 'Auto rescale', description: 'checkbox label' })}
+
+
+
+ {(focusInput || focusSlider) && (
+ {
+ setFocusSlider(true);
+ }}
+ onBlur={() => {
+ setFocusSlider(false);
+ }}
+ onMouseUp={() => {
+ setDraggingSlider(false);
+ }}
+ onMouseDown={() => {
+ setDraggingSlider(true);
+ }}
+ onChange={onSliderChange}
+ />
+ )}
+
+
+ );
+};
diff --git a/packages/scene-composer/src/components/panels/scene-settings/index.ts b/packages/scene-composer/src/components/panels/scene-settings/index.ts
index 28405fd4f..d0f255486 100644
--- a/packages/scene-composer/src/components/panels/scene-settings/index.ts
+++ b/packages/scene-composer/src/components/panels/scene-settings/index.ts
@@ -1 +1,2 @@
export * from './SceneDataBindingTemplateEditor';
+export * from './SceneTagSettingsEditor';
diff --git a/packages/scene-composer/src/components/three-fiber/EditorTransformControls.tsx b/packages/scene-composer/src/components/three-fiber/EditorTransformControls.tsx
index f3f71df4e..9b3ef03b3 100644
--- a/packages/scene-composer/src/components/three-fiber/EditorTransformControls.tsx
+++ b/packages/scene-composer/src/components/three-fiber/EditorTransformControls.tsx
@@ -26,7 +26,6 @@ export function EditorTransformControls() {
const addingWidget = useStore(sceneComposerId)((state) => state.addingWidget);
const [transformControls] = useState(() => new TransformControlsImpl(camera, domElement));
- const tagResizeEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.TagResize];
const subModelMovementEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.SubModelMovement];
const isTagComponent = useMemo(
@@ -59,7 +58,7 @@ export function EditorTransformControls() {
useEffect(() => {
if (selectedSceneNode) {
- if (isTagComponent && !tagResizeEnabled && transformControlMode === 'scale') {
+ if (isTagComponent && transformControlMode === 'scale') {
// Prevent the scale from being enabled
setTransformControlsMode('translate');
}
diff --git a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/ObjectItemGroup.tsx b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/ObjectItemGroup.tsx
index 8c11cf966..96a7985e9 100644
--- a/packages/scene-composer/src/components/toolbars/floatingToolbar/items/ObjectItemGroup.tsx
+++ b/packages/scene-composer/src/components/toolbars/floatingToolbar/items/ObjectItemGroup.tsx
@@ -19,7 +19,7 @@ enum TransformTypes {
const labelStrings = defineMessages({
[TransformTypes.Translate]: { defaultMessage: 'Translate', description: 'Menu label' },
[TransformTypes.Rotate]: { defaultMessage: 'Rotate', description: 'Menu label' },
- [TransformTypes.Scale]: { defaultMessage: 'Translate', description: 'Menu label' },
+ [TransformTypes.Scale]: { defaultMessage: 'Scale', description: 'Menu label' },
});
const textStrings = defineMessages({
@@ -35,8 +35,6 @@ export function ObjectItemGroup() {
const { getSceneNodeByRef, removeSceneNode } = useSceneDocument(sceneComposerId);
const { formatMessage } = useIntl();
- const tagResizeEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.TagResize];
-
const isTagComponent = useMemo(() => {
const selectedSceneNode = getSceneNodeByRef(selectedSceneNodeRef);
return selectedSceneNode?.components.some((component) => component.type === KnownComponentType.Tag) === true;
@@ -57,7 +55,7 @@ export function ObjectItemGroup() {
icon: { scale: 1.06, svg: ScaleIconSvg },
uuid: TransformTypes.Scale,
mode: 'scale',
- isDisabled: isTagComponent && !tagResizeEnabled,
+ isDisabled: isTagComponent,
},
].map(
(item) =>
diff --git a/packages/scene-composer/src/interfaces/componentSettings.ts b/packages/scene-composer/src/interfaces/componentSettings.ts
new file mode 100644
index 000000000..2c41ac5ac
--- /dev/null
+++ b/packages/scene-composer/src/interfaces/componentSettings.ts
@@ -0,0 +1,9 @@
+import { KnownComponentType } from './components';
+
+export interface ITagSettings {
+ scale: number;
+ autoRescale: boolean;
+}
+
+export type IComponentSettings = ITagSettings | any;
+export type IComponentSettingsMap = Record;
diff --git a/packages/scene-composer/src/interfaces/index.ts b/packages/scene-composer/src/interfaces/index.ts
index cce7036d4..fcad1a7a2 100644
--- a/packages/scene-composer/src/interfaces/index.ts
+++ b/packages/scene-composer/src/interfaces/index.ts
@@ -6,3 +6,4 @@ export * from './metricRecorder';
export * from './feature';
export * from './sceneComposerInternal';
export * from './sceneViewer';
+export * from './componentSettings';
diff --git a/packages/scene-composer/src/interfaces/interfaces.tsx b/packages/scene-composer/src/interfaces/interfaces.tsx
index 1f1061291..d67d2569c 100644
--- a/packages/scene-composer/src/interfaces/interfaces.tsx
+++ b/packages/scene-composer/src/interfaces/interfaces.tsx
@@ -68,6 +68,7 @@ export enum KnownSceneProperty {
BaseUrl = 'baseUrl',
EnvironmentPreset = 'environmentPreset',
DataBindingConfig = 'dataBindingConfig',
+ ComponentSettings = 'componentSettings',
}
/************************************************
diff --git a/packages/scene-composer/src/utils/componentSettingsUtils.spec.ts b/packages/scene-composer/src/utils/componentSettingsUtils.spec.ts
new file mode 100644
index 000000000..79a60a9e0
--- /dev/null
+++ b/packages/scene-composer/src/utils/componentSettingsUtils.spec.ts
@@ -0,0 +1,27 @@
+import { DEFAULT_TAG_GLOBAL_SETTINGS } from '../common/constants';
+import { KnownComponentType } from '../interfaces';
+
+import { componentSettingsSelector } from './componentSettingsUtils';
+
+describe('componentSettingsUtils', () => {
+ describe('componentSettingsSelector', () => {
+ it('should return default tag settings', () => {
+ const state = { getSceneProperty: jest.fn() } as any;
+ const tagSettings = componentSettingsSelector(state, KnownComponentType.Tag);
+ expect(tagSettings).toEqual(DEFAULT_TAG_GLOBAL_SETTINGS);
+ });
+
+ it('should return tag settings from scene', () => {
+ const expected = { scale: 1.6, autoRescale: true };
+ const state = { getSceneProperty: jest.fn().mockReturnValue({ Tag: expected }) } as any;
+ const tagSettings = componentSettingsSelector(state, KnownComponentType.Tag);
+ expect(tagSettings).toEqual(expected);
+ });
+
+ it('should return empty settings for unknown component type', () => {
+ const state = { getSceneProperty: jest.fn() } as any;
+ const settings = componentSettingsSelector(state, 'Random' as any);
+ expect(settings).toEqual({});
+ });
+ });
+});
diff --git a/packages/scene-composer/src/utils/componentSettingsUtils.ts b/packages/scene-composer/src/utils/componentSettingsUtils.ts
new file mode 100644
index 000000000..cedaa39f5
--- /dev/null
+++ b/packages/scene-composer/src/utils/componentSettingsUtils.ts
@@ -0,0 +1,18 @@
+import { RootState } from '../store';
+import { KnownSceneProperty, IComponentSettings, KnownComponentType } from '../interfaces';
+import { DEFAULT_TAG_GLOBAL_SETTINGS } from '../common/constants';
+
+export const componentSettingsSelector = (state: RootState, componentType: KnownComponentType): IComponentSettings => {
+ const settings = state.getSceneProperty(KnownSceneProperty.ComponentSettings)?.[componentType];
+ if (settings) {
+ return settings;
+ } else {
+ // When the settings is not in scene file, return the default setting for each component type.
+ switch (componentType) {
+ case KnownComponentType.Tag:
+ return DEFAULT_TAG_GLOBAL_SETTINGS;
+ default:
+ return {};
+ }
+ }
+};
diff --git a/packages/scene-composer/stories/SceneComposer.stories.tsx b/packages/scene-composer/stories/SceneComposer.stories.tsx
index e142d3f55..6d0ec7f14 100644
--- a/packages/scene-composer/stories/SceneComposer.stories.tsx
+++ b/packages/scene-composer/stories/SceneComposer.stories.tsx
@@ -151,7 +151,7 @@ const knobsConfigurationDecorator = [
[COMPOSER_FEATURES.ENHANCED_EDITING]: true,
[COMPOSER_FEATURES.CameraView]: true,
[COMPOSER_FEATURES.EnvironmentModel]: false,
- [COMPOSER_FEATURES.TagResize]: false,
+ [COMPOSER_FEATURES.TagResize]: true,
[COMPOSER_FEATURES.SubModelMovement]: false,
...args.config.featureConfig,
},
diff --git a/packages/scene-composer/tests/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.spec.tsx b/packages/scene-composer/tests/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.spec.tsx
deleted file mode 100644
index 633e0d200..000000000
--- a/packages/scene-composer/tests/augmentations/components/three-fiber/common/SvgIconToWidgetSprite.spec.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import renderer from 'react-test-renderer';
-import React from 'react';
-
-import { DefaultAnchorStatus, SelectedAnchor } from '../../../../../src';
-import {
- ErrorIconSvgString,
- InfoIconSvgString,
- SelectedIconSvgString,
- VideoIconSvgString,
- WarningIconSvgString,
-} from '../../../../../src/assets';
-import svgIconToWidgetSprite from '../../../../../src/augmentations/components/three-fiber/common/SvgIconToWidgetSprite';
-
-describe('svgIconToWidgetSprite', () => {
- [
- ['Selected', { key: SelectedAnchor, icon: SelectedIconSvgString }, false],
- ['Info', { key: DefaultAnchorStatus.Info, icon: InfoIconSvgString }, false],
- ['Warning', { key: DefaultAnchorStatus.Warning, icon: WarningIconSvgString }, false],
- ['Error', { key: DefaultAnchorStatus.Error, icon: ErrorIconSvgString }, false],
- ['Video', { key: DefaultAnchorStatus.Video, icon: VideoIconSvgString }, false],
- ['Selected', { key: SelectedAnchor, icon: SelectedIconSvgString }, true],
- ['Info', { key: DefaultAnchorStatus.Info, icon: InfoIconSvgString }, true],
- ['Warning', { key: DefaultAnchorStatus.Warning, icon: WarningIconSvgString }, true],
- ['Error', { key: DefaultAnchorStatus.Error, icon: ErrorIconSvgString }, true],
- ['Video', { key: DefaultAnchorStatus.Video, icon: VideoIconSvgString }, true],
- ].forEach((value) => {
- it(`it should render the ${value[2] ? 'always visible' : ''} ${value[0]} correctly`, () => {
- jest.spyOn(window.Math, 'random').mockReturnValue(0.1);
- const { key, icon } = value[1] as any;
- const container = renderer.create(svgIconToWidgetSprite(icon, key, value[2] as boolean));
-
- expect(container).toMatchSnapshot();
- });
- });
-});
diff --git a/packages/scene-composer/tests/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap b/packages/scene-composer/tests/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap
deleted file mode 100644
index b82386261..000000000
--- a/packages/scene-composer/tests/augmentations/components/three-fiber/common/__snapshots__/SvgIconToWidgetSprite.spec.tsx.snap
+++ /dev/null
@@ -1,1046 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`svgIconToWidgetSprite it should render the Error correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the Info correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the Selected correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the Video correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the Warning correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the always visible Error correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the always visible Info correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the always visible Selected correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the always visible Video correctly 1`] = `
-
-
-
-`;
-
-exports[`svgIconToWidgetSprite it should render the always visible Warning correctly 1`] = `
-
-
-
-`;
diff --git a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditor.spec.tsx b/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditor.spec.tsx
index 624377037..917399df9 100644
--- a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditor.spec.tsx
+++ b/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditor.spec.tsx
@@ -19,10 +19,8 @@ jest.mock('../../../../../src/components/panels/scene-components/motion-indicato
});
let sliderOnChangeCb;
-jest.mock('../../../../../src/components/panels/scene-components/motion-indicator/Slider', () => {
- const originalModule = jest.requireActual(
- '../../../../../src/components/panels/scene-components/motion-indicator/Slider',
- );
+jest.mock('../../../../../src/components/panels/Slider', () => {
+ const originalModule = jest.requireActual('../../../../../src/components/panels/Slider');
return {
...originalModule,
Slider: (...props: any[]) => {
diff --git a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditorSnap.spec.tsx b/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditorSnap.spec.tsx
index da70cd626..10f81378d 100644
--- a/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditorSnap.spec.tsx
+++ b/packages/scene-composer/tests/components/panels/scene-components/motion-indicator/SpeedEditorSnap.spec.tsx
@@ -17,10 +17,8 @@ jest.mock('../../../../../src/components/panels/scene-components/motion-indicato
};
});
-jest.mock('../../../../../src/components/panels/scene-components/motion-indicator/Slider', () => {
- const originalModule = jest.requireActual(
- '../../../../../src/components/panels/scene-components/motion-indicator/Slider',
- );
+jest.mock('../../../../../src/components/panels/Slider', () => {
+ const originalModule = jest.requireActual('../../../../../src/components/panels/Slider');
return {
...originalModule,
Slider: (...props: any[]) => {JSON.stringify(props)}
,
diff --git a/packages/scene-composer/tests/scenes/scene_2.json b/packages/scene-composer/tests/scenes/scene_2.json
index b7a179f71..a2d063691 100644
--- a/packages/scene-composer/tests/scenes/scene_2.json
+++ b/packages/scene-composer/tests/scenes/scene_2.json
@@ -225,6 +225,12 @@
},
"defaultCameraIndex": 0,
"properties": {
- "environmentPreset": "neutral"
+ "environmentPreset": "neutral",
+ "componentSettings": {
+ "Tag": {
+ "scale": 2,
+ "autoRescale": true
+ }
+ }
}
}
diff --git a/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json b/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json
index eab4b174d..2806794c4 100644
--- a/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json
+++ b/packages/scene-composer/translations/IotAppKitSceneComposer.en_US.json
@@ -27,6 +27,10 @@
"note": "Menu Item",
"text": "Rotate object"
},
+ "0awbFz": {
+ "note": "ExpandableInfoSection Title",
+ "text": "Tag Settings"
+ },
"1cVQu5": {
"note": "label for an input component selecting number of arrows",
"text": "# of arrows"
@@ -259,6 +263,10 @@
"note": "Placeholder",
"text": "Choose a speed value"
},
+ "JvqIHJ": {
+ "note": "checkbox label",
+ "text": "Auto rescale"
+ },
"Kchdc4": {
"note": "Placeholder",
"text": "Choose a rule"
@@ -303,6 +311,10 @@
"note": "label",
"text": "Add color rule"
},
+ "LztKh8": {
+ "note": "Menu label",
+ "text": "Scale"
+ },
"MZtQw3": {
"note": "75mm lens",
"text": "75mm"
@@ -679,6 +691,10 @@
"note": "Form field label",
"text": "Zoom"
},
+ "qU9dRt": {
+ "note": "Form Field label",
+ "text": "Scale"
+ },
"r0JN3A": {
"note": "Menu Item",
"text": "Orbit"