Skip to content

Commit

Permalink
feat(scene-composer): initial implementation of animations
Browse files Browse the repository at this point in the history
feat(scene-composer): reverted package-lock.json

"feat(scene-composer): removed uneeded dependency"

feat(scene-composer): removed changes to tag component

feat(scene-composer): removed unnecessary imports

feat(scene-composer): fixed tests

feat(scene-composer): fixed use effect in animationeditor to prevent extra fire

feat(scene-composer): addressed changes to databinding in the add component menu

feat(scene-composer): addressed more changes to databinding in the add component menu

feat(scene-composer): renamed animationupdater to animationcomponenteditor for consistency

feat(scene-composer): added internationalization for animation viewstate

feat(scene-composer): updated us.json

feat(scene-composer): refactored to address github feedback

feat(scene-composer): refactored tests and animationComponentEditor

feat(scene-composer): removed global variable from animationcomponent

feat(scene-composer): added comment to explain scene object fetching

feat(scene-composer): got rid of magic string and replaced it with a const

feat(scene-composer): minor cleanup

feat(scene-composer): added back animation scene model component with changes

feat(scene-composer): refactored addObject menu for animations

feat(scene-composer): added knowncomponent type to condition for adding an animation object

feat(scene-composer): refactored AnimationComponent test

feat(scene-composer): removed unnecessary dependency
  • Loading branch information
parsonjs authored and haweston committed Aug 16, 2023
1 parent 96d0351 commit 39f14cd
Show file tree
Hide file tree
Showing 33 changed files with 11,912 additions and 77 deletions.
1,833 changes: 1,833 additions & 0 deletions packages/scene-composer/public/AIMIMATED_MIXER.gltf

Large diffs are not rendered by default.

8,929 changes: 8,929 additions & 0 deletions packages/scene-composer/public/ANIME_VERTICAL_CONVEYOR.gltf

Large diffs are not rendered by default.

137 changes: 137 additions & 0 deletions packages/scene-composer/public/animation-test-scene.scene.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"specVersion": "1.0",
"version": "1",
"unit": "meters",
"properties": {
"environmentPreset": "neutral"
},
"nodes": [
{
"name": "ANIME_VERTICAL_CONVEYOR",
"transform": {
"position": [
-0.4911785102853923,
-5.947704102788684e-16,
-2.6786077981029086
],
"rotation": [
0,
0,
0
],
"scale": [
1,
1,
1
]
},
"transformConstraint": {},
"components": [
{
"type": "ModelRef",
"uri": "ANIME_VERTICAL_CONVEYOR.gltf",
"modelType": "GLTF"
},
{
"currentAnimations": [],
"uri": "ANIME_VERTICAL_CONVEYOR.gltf",
"type": "Animation"
}
],
"properties": {}
},
{
"name": "AIMIMATED_MIXER",
"transform": {
"position": [
-0.2548017433916856,
0.1565180250896893,
1.9222755178165505
],
"rotation": [
0,
0,
0
],
"scale": [
1,
1,
1
]
},
"transformConstraint": {},
"components": [
{
"type": "ModelRef",
"uri": "AIMIMATED_MIXER.gltf",
"modelType": "GLTF"
},
{
"currentAnimations": [],
"uri": "AIMIMATED_MIXER.gltf",
"type": "Animation"
}
],
"properties": {}
}
],
"rootNodeIndexes": [
0,
1
],
"cameras": [],
"rules": {
"sampleAlarmIconRule": {
"statements": [
{
"expression": "alarm_status == 'ACTIVE'",
"target": "iottwinmaker.common.icon:Error"
},
{
"expression": "alarm_status == 'ACKNOWLEDGED'",
"target": "iottwinmaker.common.icon:Warning"
},
{
"expression": "alarm_status == 'SNOOZE_DISABLED'",
"target": "iottwinmaker.common.icon:Warning"
},
{
"expression": "alarm_status == 'NORMAL'",
"target": "iottwinmaker.common.icon:Info"
}
]
},
"sampleTimeSeriesIconRule": {
"statements": [
{
"expression": "temperature >= 40",
"target": "iottwinmaker.common.icon:Error"
},
{
"expression": "temperature >= 20",
"target": "iottwinmaker.common.icon:Warning"
},
{
"expression": "temperature < 20",
"target": "iottwinmaker.common.icon:Info"
}
]
},
"sampleTimeSeriesColorRule": {
"statements": [
{
"expression": "temperature >= 40",
"target": "iottwinmaker.common.color:#FF0000"
},
{
"expression": "temperature >= 20",
"target": "iottwinmaker.common.color:#FFFF00"
},
{
"expression": "temperature < 20",
"target": "iottwinmaker.common.color:#00FF00"
}
]
}
}
}
46 changes: 40 additions & 6 deletions packages/scene-composer/src/components/panels/AddComponentMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { sceneComposerIdContext } from '../../common/sceneComposerIdContext';
import { COMPOSER_FEATURES, KnownComponentType } from '../../interfaces';
import { Component } from '../../models/SceneModels';
import { IDataOverlayComponentInternal, useStore } from '../../store';
import { IEntityBindingComponentInternal } from '../../store/internalInterfaces';
import { IEntityBindingComponentInternal, IAnimationComponentInternal } from '../../store/internalInterfaces';
import { findComponentByType } from '../../utils/nodeUtils';
import { ToolbarItem } from '../toolbars/common/ToolbarItem';
import { ToolbarItemOptionRaw, ToolbarItemOptions } from '../toolbars/common/types';
Expand All @@ -22,6 +22,7 @@ enum ObjectTypes {
Component = 'add-component',
Overlay = 'add-component-overlay',
EntityBinding = 'add-component-entity-binding',
Animations = 'add-component-animations',
}

type AddComponentMenuItem = ToolbarItemOptions & {
Expand All @@ -32,13 +33,14 @@ const labelStrings: { [key in ObjectTypes]: MessageDescriptor } = defineMessages
[ObjectTypes.Component]: { defaultMessage: 'Add component', description: 'Menu Item label' },
[ObjectTypes.Overlay]: { defaultMessage: 'Overlay', description: 'Menu Item label' },
[ObjectTypes.EntityBinding]: { defaultMessage: 'Add entity binding', description: 'Menu Item label' },
[ObjectTypes.Animations]: { defaultMessage: 'Add Animations', description: 'Menu Item label' },
});

const textStrings = defineMessages({
[ObjectTypes.Overlay]: { defaultMessage: 'Add overlay', description: 'Menu Item' },
[ObjectTypes.EntityBinding]: { defaultMessage: 'Add entity binding', description: 'Menu Item' },
[ObjectTypes.Animations]: { defaultMessage: 'Add Animations', description: 'Menu Item' },
});

export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect }) => {
const sceneComposerId = useContext(sceneComposerIdContext);
const addComponentInternal = useStore(sceneComposerId)((state) => state.addComponentInternal);
Expand All @@ -48,10 +50,16 @@ export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect })
const { formatMessage } = useIntl();
const selectedSceneNode = getSceneNodeByRef(selectedSceneNodeRef);
const entityBindingComponentEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.DataBinding];
const AnimationComponentEnabled = getGlobalSettings().featureConfig[COMPOSER_FEATURES.Animations];
const animationComponent = findComponentByType(
selectedSceneNode,
KnownComponentType.Animation,
) as IAnimationComponentInternal;

const isTagComponent = !!findComponentByType(selectedSceneNode, KnownComponentType.Tag);
const isOverlayComponent = !!findComponentByType(selectedSceneNode, KnownComponentType.DataOverlay);
const isEntityBindingComponent = !!findComponentByType(selectedSceneNode, KnownComponentType.EntityBinding);
const isAnimationComponent = !!findComponentByType(selectedSceneNode, KnownComponentType.Animation);
const mapToMenuItem = useCallback(
(item: ToolbarItemOptionRaw): AddComponentMenuItem => {
const typeId: ObjectTypes = item.uuid as ObjectTypes;
Expand Down Expand Up @@ -84,16 +92,32 @@ export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect })
},
]
: [];

const addAnimationItem = AnimationComponentEnabled
? [
{
uuid: ObjectTypes.Animations,
isDisabled: false,
},
]
: [];
return [
{
icon: { name: 'add-plus' as IconProps.Name },
uuid: ObjectTypes.Component,
},
...addOverlayItem,
...addEntityBindingItem,
...addAnimationItem,
].map(mapToMenuItem);
}, [selectedSceneNodeRef, selectedSceneNode, isOverlayComponent, isTagComponent, entityBindingComponentEnabled]);
}, [
selectedSceneNodeRef,
selectedSceneNode,
isOverlayComponent,
isTagComponent,
isAnimationComponent,
entityBindingComponentEnabled,
AnimationComponentEnabled,
]);

const handleAddOverlay = useCallback(() => {
if (!selectedSceneNodeRef) return;
Expand All @@ -116,7 +140,6 @@ export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect })

const handleAddEntityBinding = useCallback(() => {
if (!selectedSceneNodeRef) return;

const entityBindingComponent = findComponentByType(selectedSceneNode, KnownComponentType.EntityBinding);

if (entityBindingComponent) {
Expand All @@ -134,6 +157,15 @@ export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect })
addComponentInternal(selectedSceneNodeRef, component);
}, [selectedSceneNodeRef, selectedSceneNode]);

const handleAddAnimations = useCallback(() => {
if (!selectedSceneNodeRef) return;

let selector = animationComponent.selector || 0;
selector = selector + 1;
const updatedComponent = { ...animationComponent, selector };
updateComponentInternal(selectedSceneNodeRef, updatedComponent);
}, [selectedSceneNodeRef, selectedSceneNode]);

return addComponentMenuItems.length > 1 ? (
<div style={{ width: '40px' }}>
<ToolbarItem
Expand All @@ -142,14 +174,16 @@ export const AddComponentMenu: React.FC<AddComponentMenuProps> = ({ onSelect })
type='action-select'
onClick={({ uuid }) => {
switch (uuid) {
case ObjectTypes.Animations:
handleAddAnimations();
break;
case ObjectTypes.EntityBinding:
handleAddEntityBinding();
break;
case ObjectTypes.Overlay:
handleAddOverlay();
break;
}

onSelect?.(uuid);
getGlobalSettings().metricRecorder?.recordClick(uuid);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ jest.mock('./scene-components/LightComponentEditor', () => ({
LightComponentEditor: (props) => <div data-mocked='LightComponentEditor'>{JSON.stringify(props)}</div>,
}));

jest.mock('./scene-components/AnimationComponentEditor', () => ({
AnimationComponentEditor: (props) => <div data-mocked='AnimationComponentEditor'>{JSON.stringify(props)}</div>,
}));

jest.mock('./scene-components/ColorOverlayComponentEditor', () => ({
ColorOverlayComponentEditor: (props) => <div data-mocked='ColorOverlayComponentEditor'>{JSON.stringify(props)}</div>,
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FormField, Input, SpaceBetween } from '@awsui/components-react';
import { IDataOverlayComponentInternal, ISceneComponentInternal, ISceneNodeInternal } from '../../store';
import { KnownComponentType } from '../../interfaces';
import { pascalCase } from '../../utils/stringUtils';
import { IEntityBindingComponentInternal } from '../../store/internalInterfaces';
import { IAnimationComponentInternal, IEntityBindingComponentInternal } from '../../store/internalInterfaces';

import { AnchorComponentEditor } from './scene-components/AnchorComponentEditor';
import { LightComponentEditor } from './scene-components/LightComponentEditor';
Expand All @@ -14,6 +14,7 @@ import { MotionIndicatorComponentEditor } from './scene-components/MotionIndicat
import CameraComponentEditor from './scene-components/CameraComponentEditor';
import { DataOverlayComponentEditor } from './scene-components/DataOverlayComponentEditor';
import { EntityBindingComponentEditor } from './scene-components/EntityBindingComponentEditor';
import { AnimationComponentEditor } from './scene-components/AnimationComponentEditor';

export interface IComponentEditorProps {
node: ISceneNodeInternal;
Expand Down Expand Up @@ -58,6 +59,8 @@ export const ComponentEditor: React.FC<IComponentEditorProps> = ({ node, compone
return <DataOverlayComponentEditor node={node} component={component as IDataOverlayComponentInternal} />;
case KnownComponentType.EntityBinding:
return <EntityBindingComponentEditor node={node} component={component as IEntityBindingComponentInternal} />;
case KnownComponentType.Animation:
return <AnimationComponentEditor node={node} component={component as IAnimationComponentInternal} />;
default:
return <DefaultComponentEditor node={node} component={component} />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export const SceneNodeInspectorPanel: React.FC = () => {
defaultMessage: 'Overlay',
description: 'Expandable Section title',
},
[KnownComponentType.Animation]: {
defaultMessage: 'Animation',
description: 'Expandable Section title',
},
});

log?.verbose('render inspect panel with selected scene node ', selectedSceneNodeRef, selectedSceneNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ export const SettingsPanel: React.FC<SettingsPanelProps> = ({ valueDataBindingPr
defaultMessage: 'Overlay',
description: 'Sub section label',
},
[KnownComponentType.Animation]: {
defaultMessage: 'Animation',
description: 'Sub section label',
},
[Component.DataOverlaySubType.TextAnnotation]: {
defaultMessage: 'Annotation',
description: 'Sub section label',
Expand Down Expand Up @@ -108,6 +112,11 @@ export const SettingsPanel: React.FC<SettingsPanelProps> = ({ valueDataBindingPr
</Box>
}
>
<ComponentVisibilityToggle
componentType={KnownComponentType.Animation}
label={intl.formatMessage(visibilityToggleLabels[KnownComponentType.Animation])}
/>
<Divider />
<ComponentVisibilityToggle
componentType={KnownComponentType.MotionIndicator}
label={intl.formatMessage(visibilityToggleLabels[KnownComponentType.MotionIndicator])}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ exports[`ComponentEditor renders correct component render DefaultComponentEditor
</div>
`;

exports[`ComponentEditor renders correct component should render the "Animation" editor correctly 1`] = `
<div>
<div
data-mocked="AnimationComponentEditor"
>
{"node":{},"component":{"ref":"refId","type":"Animation"}}
</div>
</div>
`;

exports[`ComponentEditor renders correct component should render the "Camera" editor correctly 1`] = `
<div>
<div
Expand Down

0 comments on commit 39f14cd

Please sign in to comment.