├── .prettierignore
├── src
├── typings
│ ├── jszip
│ │ └── typings.d.ts
│ ├── svgo
│ │ └── typings.d.ts
│ ├── bezier-js
│ │ └── typings.d.ts
│ ├── deep-freeze-strict
│ │ └── typings.d.ts
│ ├── element-resize-detector
│ │ └── typings.d.ts
│ ├── common.d.ts
│ └── paper
│ │ ├── HitOptions.d.ts
│ │ ├── PlacedSymbol.d.ts
│ │ ├── PointText.d.ts
│ │ ├── Group.d.ts
│ │ ├── TextItem.d.ts
│ │ ├── Symbol.d.ts
│ │ ├── Layer.d.ts
│ │ ├── HitResult.d.ts
│ │ ├── paper.d.ts
│ │ └── CompoundPath.d.ts
├── app
│ └── modules
│ │ └── editor
│ │ ├── components
│ │ ├── splitter
│ │ │ ├── splitter.component.html
│ │ │ └── splitter.component.scss
│ │ ├── project
│ │ │ ├── index.ts
│ │ │ └── project.service.ts
│ │ ├── playback
│ │ │ ├── index.ts
│ │ │ ├── _playback-theme.scss
│ │ │ ├── playback.component.html
│ │ │ ├── playback.component.ts
│ │ │ └── playback.component.scss
│ │ ├── layertimeline
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── _timelineanimationrow-theme.scss
│ │ │ ├── timelineanimationrow.component.scss
│ │ │ ├── _layerlisttree-theme.scss
│ │ │ └── timelineanimationrow.component.html
│ │ ├── propertyinput
│ │ │ ├── index.ts
│ │ │ ├── _propertyinput-theme.scss
│ │ │ └── InspectedProperty.ts
│ │ ├── dialogs
│ │ │ ├── confirmdialog.component.scss
│ │ │ ├── dropfilesdialog.component.scss
│ │ │ ├── index.ts
│ │ │ ├── _dialog-theme.scss
│ │ │ ├── demodialog.component.scss
│ │ │ ├── confirmdialog.component.ts
│ │ │ ├── demodialog.component.ts
│ │ │ ├── dialog.service.ts
│ │ │ └── dropfilesdialog.component.ts
│ │ ├── splashscreen
│ │ │ ├── splashscreen.component.html
│ │ │ ├── splashscreen.component.ts
│ │ │ └── splashscreen.component.scss
│ │ ├── canvas
│ │ │ ├── _canvas-theme.scss
│ │ │ ├── index.ts
│ │ │ ├── canvascontainer.directive.ts
│ │ │ ├── canvas.component.scss
│ │ │ ├── canvas.component.html
│ │ │ ├── canvaspaper.directive.ts
│ │ │ ├── CanvasUtil.ts
│ │ │ └── CanvasLayoutMixin.ts
│ │ ├── toolpanel
│ │ │ ├── toolpanel.component.scss
│ │ │ └── toolpanel.component.ts
│ │ ├── root
│ │ │ ├── _root-theme.scss
│ │ │ └── root.component.html
│ │ ├── toolbar
│ │ │ ├── _toolbar-theme.scss
│ │ │ └── toolbar.component.scss
│ │ └── scrollgroup
│ │ │ └── scrollgroup.directive.ts
│ │ ├── scripts
│ │ ├── dragger
│ │ │ └── index.ts
│ │ ├── paper
│ │ │ ├── gesture
│ │ │ │ ├── index.ts
│ │ │ │ ├── hover
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── HoverGesture.ts
│ │ │ │ ├── scale
│ │ │ │ │ └── index.ts
│ │ │ │ ├── transform
│ │ │ │ │ └── index.ts
│ │ │ │ ├── rotate
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── RotateItemsDragPivotGesture.ts
│ │ │ │ ├── create
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── EllipseGesture.ts
│ │ │ │ │ └── RectangleGesture.ts
│ │ │ │ ├── select
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── DeselectItemGesture.ts
│ │ │ │ │ ├── EditPathGesture.ts
│ │ │ │ │ └── BatchSelectItemsGesture.ts
│ │ │ │ ├── edit
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── ToggleSegmentHandlesGesture.ts
│ │ │ │ └── Gesture.ts
│ │ │ ├── detector
│ │ │ │ ├── index.ts
│ │ │ │ └── Handler.ts
│ │ │ ├── tool
│ │ │ │ ├── index.ts
│ │ │ │ ├── Tool.ts
│ │ │ │ └── MasterToolPicker.ts
│ │ │ ├── util
│ │ │ │ ├── snap
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── Constants.ts
│ │ │ │ │ └── SnapBounds.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── PivotType.ts
│ │ │ ├── item
│ │ │ │ ├── index.ts
│ │ │ │ ├── EditPathRaster.ts
│ │ │ │ ├── RotateItemsPivotRaster.ts
│ │ │ │ └── SelectionBoundsRaster.ts
│ │ │ └── index.ts
│ │ ├── intervals
│ │ │ ├── index.ts
│ │ │ └── IntervalTree.ts
│ │ ├── mixins
│ │ │ ├── index.ts
│ │ │ └── DestroyableMixin.ts
│ │ ├── animator
│ │ │ └── index.ts
│ │ ├── algorithms
│ │ │ ├── index.ts
│ │ │ ├── AutoAwesome.spec.ts
│ │ │ └── NeedlemanWunsch.ts
│ │ ├── common
│ │ │ ├── Point.ts
│ │ │ ├── Rect.ts
│ │ │ ├── index.ts
│ │ │ ├── MathUtil.spec.ts
│ │ │ ├── Matrix.spec.ts
│ │ │ ├── ColorUtil.spec.ts
│ │ │ └── MathUtil.ts
│ │ ├── actionmode
│ │ │ ├── index.ts
│ │ │ └── ActionModeUtil.ts
│ │ ├── import
│ │ │ └── index.ts
│ │ ├── export
│ │ │ └── index.ts
│ │ ├── demos
│ │ │ └── index.ts
│ │ └── bugsnag
│ │ │ └── index.ts
│ │ ├── model
│ │ ├── interpolators
│ │ │ └── index.ts
│ │ ├── paper
│ │ │ ├── index.ts
│ │ │ ├── ToolMode.ts
│ │ │ └── CursorType.ts
│ │ ├── paths
│ │ │ ├── calculators
│ │ │ │ ├── index.ts
│ │ │ │ ├── MoveCalculator.ts
│ │ │ │ ├── PointCalculator.ts
│ │ │ │ └── Calculator.ts
│ │ │ ├── SvgChar.ts
│ │ │ ├── index.ts
│ │ │ └── PathUtil.ts
│ │ ├── actionmode
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── timeline
│ │ │ ├── index.ts
│ │ │ └── Animation.ts
│ │ ├── layers
│ │ │ ├── index.ts
│ │ │ └── layers.spec.ts
│ │ └── properties
│ │ │ ├── PropertyMaps.ts
│ │ │ ├── index.ts
│ │ │ ├── FractionProperty.ts
│ │ │ ├── NameProperty.ts
│ │ │ ├── EnumProperty.ts
│ │ │ ├── ColorProperty.ts
│ │ │ ├── PathProperty.ts
│ │ │ └── NumberProperty.ts
│ │ ├── styles
│ │ ├── app.scss
│ │ ├── root.scss
│ │ └── material-icons.scss
│ │ ├── store
│ │ ├── index.ts
│ │ ├── reset
│ │ │ ├── selectors.ts
│ │ │ ├── reducer.ts
│ │ │ ├── actions.ts
│ │ │ └── metareducer.ts
│ │ ├── selectors.ts
│ │ ├── theme
│ │ │ ├── selectors.ts
│ │ │ ├── actions.ts
│ │ │ └── reducer.ts
│ │ ├── batch
│ │ │ ├── actions.ts
│ │ │ └── metareducer.ts
│ │ ├── storefreeze
│ │ │ └── metareducer.ts
│ │ ├── layers
│ │ │ ├── selectors.ts
│ │ │ ├── reducer.ts
│ │ │ └── actions.ts
│ │ ├── timeline
│ │ │ ├── reducer.ts
│ │ │ ├── actions.ts
│ │ │ └── selectors.ts
│ │ ├── playback
│ │ │ ├── reducer.ts
│ │ │ ├── selectors.ts
│ │ │ └── actions.ts
│ │ ├── undoredo
│ │ │ └── metareducer.ts
│ │ ├── actionmode
│ │ │ └── actions.ts
│ │ ├── reducer.ts
│ │ └── common
│ │ │ └── selectors.ts
│ │ └── services
│ │ ├── snackbar.service.ts
│ │ ├── StoreUtil.ts
│ │ ├── index.ts
│ │ └── theme.service.ts
├── favicon.ico
├── assets
│ ├── cursor
│ │ ├── pen.png
│ │ ├── pencil.png
│ │ ├── pen-add.png
│ │ ├── crosshair.png
│ │ ├── pen-close.png
│ │ ├── rotate-left.png
│ │ ├── rotate-top.png
│ │ ├── point-select.png
│ │ ├── rotate-bottom.png
│ │ ├── rotate-right.png
│ │ ├── rotate-top-left.png
│ │ ├── rotate-top-right.png
│ │ ├── rotate-bottom-left.png
│ │ └── rotate-bottom-right.png
│ ├── screencap.jpg
│ ├── shapeshifter.png
│ ├── paper
│ │ ├── vector-handle.png
│ │ ├── vector-segment.png
│ │ ├── rotate-items-pivot.png
│ │ ├── vector-handle-selected.png
│ │ ├── selection-bounds-segment.png
│ │ ├── transform-bounds-segment.png
│ │ ├── vector-segment-selected.png
│ │ └── transform-bounds-segment-selected.png
│ ├── icons
│ │ ├── pauseplay-white.png
│ │ ├── playpause-white.png
│ │ ├── reverse.svg
│ │ ├── autofix.svg
│ │ ├── addlayer.svg
│ │ ├── grouplayer.svg
│ │ ├── collection.svg
│ │ ├── animationblock.svg
│ │ ├── vectorlayer.svg
│ │ ├── clippathlayer.svg
│ │ ├── animation.svg
│ │ ├── contribute.svg
│ │ └── pathlayer.svg
│ ├── tools
│ │ ├── tool_select.svg
│ │ ├── tool_rectangle.svg
│ │ ├── tool_vector.svg
│ │ ├── tool_pencil.svg
│ │ ├── tool_zoompan.svg
│ │ └── tool_ellipse.svg
│ └── shapeshifter.svg
├── styles.scss
├── environments
│ ├── environment.ts
│ ├── environment.beta.dev.ts
│ ├── environment.beta.prod.ts
│ ├── environment.stable.prod.ts
│ └── version.ts
├── tsconfig.spec.json
├── manifest.json
├── tsconfig.app.json
├── main.ts
├── test.ts
├── index.html
└── demos
│ └── playtopause.shapeshifter
├── art
├── cast.gif
├── animals.gif
├── digits.gif
├── moreback.gif
├── plusminus.gif
├── screencap.gif
├── drawerarrow.gif
├── expandcollapse.gif
├── playpausestop.gif
└── droidcon-sf-video-embed.png
├── scripts
├── deploy-stable.sh
├── deploy-beta.sh
└── check-node-version.js
├── .prettierrc
├── e2e
├── app.po.ts
├── app.e2e-spec.ts
└── tsconfig.e2e.json
├── coverconfig.json
├── .editorconfig
├── ngsw-config.json
├── .vscode
└── settings.json
├── .travis.yml
├── .gitignore
├── tsconfig.json
├── protractor.conf.js
└── karma.conf.js
/.prettierignore:
--------------------------------------------------------------------------------
1 | package.json
2 |
--------------------------------------------------------------------------------
/src/typings/jszip/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'jszip';
2 |
--------------------------------------------------------------------------------
/src/typings/svgo/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'svgo/*';
2 |
--------------------------------------------------------------------------------
/src/typings/bezier-js/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'bezier-js';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/splitter/splitter.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/art/cast.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/cast.gif
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/dragger/index.ts:
--------------------------------------------------------------------------------
1 | export { Dragger } from './Dragger';
2 |
--------------------------------------------------------------------------------
/src/typings/deep-freeze-strict/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'deep-freeze-strict';
2 |
--------------------------------------------------------------------------------
/art/animals.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/animals.gif
--------------------------------------------------------------------------------
/art/digits.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/digits.gif
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/art/moreback.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/moreback.gif
--------------------------------------------------------------------------------
/art/plusminus.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/plusminus.gif
--------------------------------------------------------------------------------
/art/screencap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/screencap.gif
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/index.ts:
--------------------------------------------------------------------------------
1 | export { Gesture } from './Gesture';
2 |
--------------------------------------------------------------------------------
/src/typings/element-resize-detector/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'element-resize-detector';
2 |
--------------------------------------------------------------------------------
/art/drawerarrow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/drawerarrow.gif
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/intervals/index.ts:
--------------------------------------------------------------------------------
1 | export { IntervalTree } from './IntervalTree';
2 |
--------------------------------------------------------------------------------
/art/expandcollapse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/expandcollapse.gif
--------------------------------------------------------------------------------
/art/playpausestop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/playpausestop.gif
--------------------------------------------------------------------------------
/src/app/modules/editor/components/project/index.ts:
--------------------------------------------------------------------------------
1 | export { ProjectService } from './project.service';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/mixins/index.ts:
--------------------------------------------------------------------------------
1 | export { DestroyableMixin } from './DestroyableMixin';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/detector/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickDetector } from './ClickDetector';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/playback/index.ts:
--------------------------------------------------------------------------------
1 | export { PlaybackComponent } from './playback.component';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/animator/index.ts:
--------------------------------------------------------------------------------
1 | export { AnimationRenderer } from './AnimationRenderer';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/hover/index.ts:
--------------------------------------------------------------------------------
1 | export { HoverGesture } from './HoverGesture';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/tool/index.ts:
--------------------------------------------------------------------------------
1 | export { MasterToolPicker } from './MasterToolPicker';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/pen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/pen.png
--------------------------------------------------------------------------------
/src/assets/screencap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/screencap.jpg
--------------------------------------------------------------------------------
/src/app/modules/editor/components/layertimeline/constants.ts:
--------------------------------------------------------------------------------
1 | export const TIMELINE_ANIMATION_PADDING = 20; // 20px
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/interpolators/index.ts:
--------------------------------------------------------------------------------
1 | export { Interpolator, INTERPOLATORS } from './Interpolator';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/pencil.png
--------------------------------------------------------------------------------
/src/assets/shapeshifter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/shapeshifter.png
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/scale/index.ts:
--------------------------------------------------------------------------------
1 | export { ScaleItemsGesture } from './ScaleItemsGesture';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/pen-add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/pen-add.png
--------------------------------------------------------------------------------
/art/droidcon-sf-video-embed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/art/droidcon-sf-video-embed.png
--------------------------------------------------------------------------------
/src/app/modules/editor/components/propertyinput/index.ts:
--------------------------------------------------------------------------------
1 | export { PropertyInputComponent } from './propertyinput.component';
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/algorithms/index.ts:
--------------------------------------------------------------------------------
1 | import * as AutoAwesome from './AutoAwesome';
2 | export { AutoAwesome };
3 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/util/snap/index.ts:
--------------------------------------------------------------------------------
1 | import * as SnapUtil from './SnapUtil';
2 | export { SnapUtil };
3 |
--------------------------------------------------------------------------------
/src/assets/cursor/crosshair.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/crosshair.png
--------------------------------------------------------------------------------
/src/assets/cursor/pen-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/pen-close.png
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-left.png
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-top.png
--------------------------------------------------------------------------------
/src/app/modules/editor/model/paper/index.ts:
--------------------------------------------------------------------------------
1 | export { ToolMode } from './ToolMode';
2 | export { CursorType } from './CursorType';
3 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/common/Point.ts:
--------------------------------------------------------------------------------
1 | export interface Point {
2 | readonly x: number;
3 | readonly y: number;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/transform/index.ts:
--------------------------------------------------------------------------------
1 | export { TransformPathsGesture } from './TransformPathsGesture';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/point-select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/point-select.png
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-bottom.png
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-right.png
--------------------------------------------------------------------------------
/src/assets/paper/vector-handle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/vector-handle.png
--------------------------------------------------------------------------------
/src/assets/paper/vector-segment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/vector-segment.png
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/actionmode/index.ts:
--------------------------------------------------------------------------------
1 | import * as ActionModeUtil from './ActionModeUtil';
2 | export { ActionModeUtil };
3 |
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-top-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-top-left.png
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-top-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-top-right.png
--------------------------------------------------------------------------------
/src/assets/icons/pauseplay-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/icons/pauseplay-white.png
--------------------------------------------------------------------------------
/src/assets/icons/playpause-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/icons/playpause-white.png
--------------------------------------------------------------------------------
/src/app/modules/editor/model/paths/calculators/index.ts:
--------------------------------------------------------------------------------
1 | export { Calculator, newCalculator, Projection, BBox, Line } from './Calculator';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-bottom-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-bottom-left.png
--------------------------------------------------------------------------------
/src/assets/paper/rotate-items-pivot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/rotate-items-pivot.png
--------------------------------------------------------------------------------
/src/app/modules/editor/model/actionmode/index.ts:
--------------------------------------------------------------------------------
1 | export { ActionMode, ActionSource, Hover, HoverType, Selection, SelectionType } from './types';
2 |
--------------------------------------------------------------------------------
/src/assets/cursor/rotate-bottom-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/cursor/rotate-bottom-right.png
--------------------------------------------------------------------------------
/src/assets/paper/vector-handle-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/vector-handle-selected.png
--------------------------------------------------------------------------------
/src/app/modules/editor/styles/app.scss:
--------------------------------------------------------------------------------
1 | // Core page layouts and common stuff.
2 | @import 'root';
3 | // Material design theme.
4 | @import 'theme';
5 |
--------------------------------------------------------------------------------
/src/assets/paper/selection-bounds-segment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/selection-bounds-segment.png
--------------------------------------------------------------------------------
/src/assets/paper/transform-bounds-segment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/transform-bounds-segment.png
--------------------------------------------------------------------------------
/src/assets/paper/vector-segment-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/vector-segment-selected.png
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | @import './app/modules/editor/styles/app.scss';
4 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: false,
3 | beta: false,
4 | analyticsTrackingId: 'UA-92075411-1',
5 | };
6 |
--------------------------------------------------------------------------------
/src/environments/environment.beta.dev.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: false,
3 | beta: true,
4 | analyticsTrackingId: 'UA-92075411-2',
5 | };
6 |
--------------------------------------------------------------------------------
/src/environments/environment.beta.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | beta: true,
4 | analyticsTrackingId: 'UA-92075411-2',
5 | };
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/paths/SvgChar.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The different types of supported SVG commands.
3 | */
4 | export type SvgChar = 'M' | 'L' | 'Q' | 'C' | 'Z';
5 |
--------------------------------------------------------------------------------
/src/assets/paper/transform-bounds-segment-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexjlockwood/ShapeShifter/HEAD/src/assets/paper/transform-bounds-segment-selected.png
--------------------------------------------------------------------------------
/src/environments/environment.stable.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | beta: false,
4 | analyticsTrackingId: 'UA-92075411-1',
5 | };
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/index.ts:
--------------------------------------------------------------------------------
1 | export { StoreModule, Store, Action, ActionReducer } from '@ngrx/store';
2 | export { State, reducers, metaReducers } from './reducer';
3 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/common/Rect.ts:
--------------------------------------------------------------------------------
1 | export interface Rect {
2 | readonly l: number;
3 | readonly t: number;
4 | readonly r: number;
5 | readonly b: number;
6 | }
7 |
--------------------------------------------------------------------------------
/scripts/deploy-stable.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | npm i
4 | npm run build
5 | echo "shapeshifter.design" > dist/CNAME
6 | ngh --repo git@github.com:alexjlockwood/ShapeShifterStable.git
7 |
--------------------------------------------------------------------------------
/scripts/deploy-beta.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | npm i
4 | npm run build-beta
5 | echo "beta.shapeshifter.design" > dist/CNAME
6 | ngh --repo git@github.com:alexjlockwood/ShapeShifterBeta.git
7 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/import/index.ts:
--------------------------------------------------------------------------------
1 | import * as SvgLoader from './SvgLoader';
2 | import * as VectorDrawableLoader from './VectorDrawableLoader';
3 | export { SvgLoader, VectorDrawableLoader };
4 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/rotate/index.ts:
--------------------------------------------------------------------------------
1 | export { RotateItemsGesture } from './RotateItemsGesture';
2 | export { RotateItemsDragPivotGesture } from './RotateItemsDragPivotGesture';
3 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/util/index.ts:
--------------------------------------------------------------------------------
1 | import * as PaperUtil from './PaperUtil';
2 | export { PaperUtil };
3 | export { PivotType } from './PivotType';
4 | export { SnapUtil } from './snap';
5 |
--------------------------------------------------------------------------------
/src/environments/version.ts:
--------------------------------------------------------------------------------
1 | import { environment } from './environment';
2 |
3 | export const version = `${require('../../package.json').version}-${
4 | environment.beta ? 'beta' : 'stable'
5 | }`;
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/paper/ToolMode.ts:
--------------------------------------------------------------------------------
1 | export enum ToolMode {
2 | Default = 'Default',
3 | Pencil = 'Pencil',
4 | Ellipse = 'Ellipse',
5 | Rectangle = 'Rectangle',
6 | ZoomPan = 'ZoomPan',
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_select.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/create/index.ts:
--------------------------------------------------------------------------------
1 | export { RectangleGesture } from './RectangleGesture';
2 | export { EllipseGesture } from './EllipseGesture';
3 | export { PencilGesture } from './PencilGesture';
4 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/timeline/index.ts:
--------------------------------------------------------------------------------
1 | export { Animation } from './Animation';
2 | export {
3 | AnimationBlock,
4 | PathAnimationBlock,
5 | ColorAnimationBlock,
6 | NumberAnimationBlock,
7 | } from './AnimationBlock';
8 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_rectangle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/item/index.ts:
--------------------------------------------------------------------------------
1 | import * as HitTests from './HitTests';
2 | export { HitTests };
3 |
4 | export { PaperLayer, HitResult } from './PaperLayer';
5 | export { SelectionBoundsRaster } from './SelectionBoundsRaster';
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true,
4 | "trailingComma": "all",
5 | "overrides": [
6 | {
7 | "files": "*.scss",
8 | "options": {
9 | "tabWidth": 4
10 | }
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/util/PivotType.ts:
--------------------------------------------------------------------------------
1 | export type PivotType =
2 | | 'bottomLeft'
3 | | 'leftCenter'
4 | | 'topLeft'
5 | | 'topCenter'
6 | | 'topRight'
7 | | 'rightCenter'
8 | | 'bottomRight'
9 | | 'bottomCenter';
10 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/dialogs/confirmdialog.component.scss:
--------------------------------------------------------------------------------
1 | button {
2 | text-transform: uppercase;
3 | &:mat-dialog-close {
4 | margin-right: 8px;
5 | }
6 | }
7 |
8 | mat-dialog-actions {
9 | min-width: 220px;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/dialogs/dropfilesdialog.component.scss:
--------------------------------------------------------------------------------
1 | button {
2 | text-transform: uppercase;
3 | &:mat-dialog-close {
4 | margin-right: 8px;
5 | }
6 | }
7 |
8 | mat-dialog-actions {
9 | min-width: 220px;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/export/index.ts:
--------------------------------------------------------------------------------
1 | import * as AvdSerializer from './AvdSerializer';
2 | import * as SpriteSerializer from './SpriteSerializer';
3 | import * as SvgSerializer from './SvgSerializer';
4 | export { AvdSerializer, SpriteSerializer, SvgSerializer };
5 |
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, element, by } from 'protractor';
2 |
3 | export class ShapeShifterPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/coverconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "enabled": true,
3 | "relativeSourcePath": "../src",
4 | "relativeCoverageDir": "../../coverage",
5 | "ignorePatterns": ["**/node_modules/**"],
6 | "includePid": false,
7 | "reports": ["json", "html", "lcov"],
8 | "verbose": false
9 | }
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = true
14 |
--------------------------------------------------------------------------------
/src/app/modules/editor/styles/root.scss:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | width: 100%;
6 | height: 100%;
7 | overflow: hidden;
8 | }
9 |
10 | $mdFontFamily: Roboto,
11 | 'Helvetica Neue',
12 | sans-serif !default;
13 | html {
14 | font-family: $mdFontFamily;
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/reset/selectors.ts:
--------------------------------------------------------------------------------
1 | import { getEditorState } from 'app/modules/editor/store/selectors';
2 | import { createSelector } from 'reselect';
3 |
4 | const getResetState = createSelector(getEditorState, s => s.reset);
5 | export const isBeingReset = createSelector(getResetState, r => r.isBeingReset);
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/dialogs/index.ts:
--------------------------------------------------------------------------------
1 | export { ConfirmDialogComponent } from './confirmdialog.component';
2 | export { DemoDialogComponent } from './demodialog.component';
3 | export { DropFilesDialogComponent, DropFilesAction } from './dropfilesdialog.component';
4 | export { DialogService } from './dialog.service';
5 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/select/index.ts:
--------------------------------------------------------------------------------
1 | export { BatchSelectItemsGesture } from './BatchSelectItemsGesture';
2 | export { DeselectItemGesture } from './DeselectItemGesture';
3 | export { EditPathGesture } from './EditPathGesture';
4 | export { SelectDragCloneItemsGesture } from './SelectDragCloneItemsGesture';
5 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/layers/index.ts:
--------------------------------------------------------------------------------
1 | import * as LayerUtil from './LayerUtil';
2 | export { LayerUtil };
3 |
4 | export {
5 | Layer,
6 | ClipPathLayer,
7 | VectorLayer,
8 | GroupLayer,
9 | PathLayer,
10 | StrokeLineCap,
11 | StrokeLineJoin,
12 | FillType,
13 | MorphableLayer,
14 | } from './Layer';
15 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/layertimeline/index.ts:
--------------------------------------------------------------------------------
1 | export { LayerListTreeComponent } from './layerlisttree.component';
2 | export { LayerTimelineComponent } from './layertimeline.component';
3 | export { LayerTimelineGridDirective } from './layertimelinegrid.directive';
4 | export { TimelineAnimationRowComponent } from './timelineanimationrow.component';
5 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": ["jasmine", "node"]
9 | },
10 | "files": ["test.ts", "polyfills.ts"],
11 | "include": ["**/*.spec.ts", "**/*.d.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/splashscreen/splashscreen.component.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
8 |
Shape Shifter is an icon animation tool designed for desktop browsers
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/paths/index.ts:
--------------------------------------------------------------------------------
1 | import * as PathUtil from './PathUtil';
2 |
3 | export { PathUtil };
4 | export { Projection, Line } from './calculators';
5 | export { SvgChar } from './SvgChar';
6 | export { Path, HitOptions, HitResult, ProjectionOntoPath, PathMutator } from './Path';
7 | export { SubPath } from './SubPath';
8 | export { Command } from './Command';
9 |
--------------------------------------------------------------------------------
/src/assets/icons/reverse.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { ShapeShifterPage } from './app.po';
2 |
3 | describe('Shape Shifter App', function() {
4 | let page: ShapeShifterPage;
5 |
6 | beforeEach(() => {
7 | page = new ShapeShifterPage();
8 | });
9 |
10 | it('should display message saying app works', () => {
11 | page.navigateTo();
12 | expect(true).toEqual(true);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/typings/common.d.ts:
--------------------------------------------------------------------------------
1 | interface Dictionary {
2 | [index: string]: T;
3 | }
4 |
5 | // A readonly 2D array.
6 | type ReadonlyTable = ReadonlyArray>;
7 |
8 | // An object with values that can be null.
9 | type Nullable = { [P in keyof T]: T[P] | null };
10 |
11 | // A generic constructor type.
12 | type Constructor = new (...args: any[]) => T;
13 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/common/index.ts:
--------------------------------------------------------------------------------
1 | import * as ColorUtil from './ColorUtil';
2 | import * as MathUtil from './MathUtil';
3 | import * as ModelUtil from './ModelUtil';
4 | import * as TransformUtil from './TransformUtil';
5 | export * from './Matrix';
6 | export { ColorUtil, MathUtil, ModelUtil, TransformUtil };
7 | export { Point } from './Point';
8 | export { Rect } from './Rect';
9 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/splashscreen/splashscreen.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-splashscreen',
5 | templateUrl: './splashscreen.component.html',
6 | styleUrls: ['./splashscreen.component.scss'],
7 | changeDetection: ChangeDetectionStrategy.OnPush,
8 | })
9 | export class SplashScreenComponent {}
10 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/create/EllipseGesture.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | import { ShapeGesture } from './ShapeGesture';
4 |
5 | /** A gesture that creates an elliptical path. */
6 | export class EllipseGesture extends ShapeGesture {
7 | // @Override
8 | protected newPath(vpBounds: paper.Rectangle) {
9 | return new paper.Path.Ellipse(vpBounds);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/dialogs/_dialog-theme.scss:
--------------------------------------------------------------------------------
1 | @mixin ss-dialog-theme($theme) {
2 | $accent: map-get($theme, accent);
3 | $foreground: map-get($theme, ss-foreground);
4 | mat-dialog-actions {
5 | button {
6 | color: mat-color($accent);
7 | }
8 | }
9 | mat-dialog-content {
10 | color: mat-color($foreground, secondary-text);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/create/RectangleGesture.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | import { ShapeGesture } from './ShapeGesture';
4 |
5 | /** A gesture that creates a rectangular path. */
6 | export class RectangleGesture extends ShapeGesture {
7 | // @Override
8 | protected newPath(vpBounds: paper.Rectangle) {
9 | return new paper.Path.Rectangle(vpBounds);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/selectors.ts:
--------------------------------------------------------------------------------
1 | import * as _ from 'lodash';
2 | import { createSelector, createSelectorCreator, defaultMemoize } from 'reselect';
3 |
4 | import { State } from './reducer';
5 |
6 | const getState = (state: State) => state;
7 | export const getEditorState = createSelector(getState, s => s.present);
8 | export const createDeepEqualSelector = createSelectorCreator(defaultMemoize, _.isEqual);
9 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/canvas/_canvas-theme.scss:
--------------------------------------------------------------------------------
1 | @mixin ss-canvas-theme($theme) {
2 | $background: map-get($theme, ss-background);
3 | .app-canvas-container {
4 | .canvas-container {
5 | canvas.rendering-canvas {
6 | // background-color: mat-color($background, base);
7 | background-color: #fff;
8 | }
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/properties/PropertyMaps.ts:
--------------------------------------------------------------------------------
1 | import { Property } from '.';
2 |
3 | // Maps property names to inspectable properties.
4 | export interface Inspectable {
5 | readonly inspectableProperties: Map>;
6 | }
7 |
8 | // Maps property names to animatable properties.
9 | export interface Animatable {
10 | readonly animatableProperties: Map>;
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/edit/index.ts:
--------------------------------------------------------------------------------
1 | export { BatchSelectSegmentsGesture } from './BatchSelectSegmentsGesture';
2 | export { MouldCurveGesture } from './MouldCurveGesture';
3 | export { SelectDragDrawSegmentsGesture } from './SelectDragDrawSegmentsGesture';
4 | export { SelectDragHandleGesture } from './SelectDragHandleGesture';
5 | export { ToggleSegmentHandlesGesture } from './ToggleSegmentHandlesGesture';
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/dialogs/demodialog.component.scss:
--------------------------------------------------------------------------------
1 | button {
2 | text-transform: uppercase;
3 | &:mat-dialog-close {
4 | margin-right: 8px;
5 | }
6 | }
7 |
8 | mat-dialog-actions {
9 | min-width: 220px;
10 | }
11 |
12 | .dialog-radio-group {
13 | display: inline-flex;
14 | flex-direction: column;
15 | }
16 |
17 | .dialog-radio-button {
18 | margin-bottom: 16px;
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/layers/layers.spec.ts:
--------------------------------------------------------------------------------
1 | // import { VectorLayer, ClipPathLayer, GroupLayer, PathLayer } from '.';
2 | // import { Path } from '../paths';
3 |
4 | // describe('Layers', () => {
5 | // it('ClipPathLayer', () => {
6 | // const layer = new ClipPathLayer('myId', new Path('M 0 0 1 1 2 2 3 3'));
7 | // console.info(layer);
8 | // expect(layer.hasOwnProperty('id')).toBe(true);
9 | // });
10 | // });
11 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/toolpanel/toolpanel.component.scss:
--------------------------------------------------------------------------------
1 | .tool-panel {
2 | // TODO: move this into a themed CSS file
3 | background-color: #eeeeee;
4 | position: relative;
5 |
6 | .tool-button {
7 | margin: 4px;
8 | &:hover {
9 | cursor: pointer;
10 | }
11 | &.is-checked {
12 | // TODO: move this into a themed CSS file
13 | background-color: #d0d0d0;
14 | }
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/canvas/index.ts:
--------------------------------------------------------------------------------
1 | export { CanvasComponent } from './canvas.component';
2 | export { CanvasContainerDirective } from './canvascontainer.directive';
3 | export { CanvasLayersDirective } from './canvaslayers.directive';
4 | export { CanvasOverlayDirective } from './canvasoverlay.directive';
5 | export { CanvasRulerDirective } from './canvasruler.directive';
6 | export { CanvasPaperDirective } from './canvaspaper.directive';
7 |
--------------------------------------------------------------------------------
/scripts/check-node-version.js:
--------------------------------------------------------------------------------
1 | const semver = require('semver');
2 | const engines = require('../package.json').engines;
3 | const version = engines.node;
4 |
5 | if (!semver.satisfies(process.version, version)) {
6 | console.error(
7 | 'ERROR! The version of node on your machine is out of date (current: ' +
8 | process.version +
9 | ', required: ' +
10 | version +
11 | ').\n',
12 | );
13 | process.exit(1);
14 | }
15 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "sourceMap": true,
4 | "declaration": false,
5 | "moduleResolution": "node",
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "lib": [
9 | "es2016"
10 | ],
11 | "outDir": "../dist/out-tsc-e2e",
12 | "module": "commonjs",
13 | "target": "es6",
14 | "types":[
15 | "jasmine",
16 | "node"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/properties/index.ts:
--------------------------------------------------------------------------------
1 | export { ColorProperty } from './ColorProperty';
2 | export { FractionProperty } from './FractionProperty';
3 | export { NameProperty } from './NameProperty';
4 | export { NumberProperty } from './NumberProperty';
5 | export { PathProperty } from './PathProperty';
6 | export { Property } from './Property';
7 | export { Animatable, Inspectable } from './PropertyMaps';
8 | export { EnumProperty, Option } from './EnumProperty';
9 |
--------------------------------------------------------------------------------
/src/assets/icons/autofix.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/theme/selectors.ts:
--------------------------------------------------------------------------------
1 | import { getEditorState } from 'app/modules/editor/store/selectors';
2 | import { createSelector, createStructuredSelector } from 'reselect';
3 |
4 | const getThemeState = createSelector(getEditorState, s => s.theme);
5 | export const getThemeType = createStructuredSelector({
6 | themeType: createSelector(getThemeState, t => t.themeType),
7 | isInitialPageLoad: createSelector(getThemeState, t => t.isInitialPageLoad),
8 | });
9 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_vector.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ngsw-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": "/index.html",
3 | "assetGroups": [
4 | {
5 | "name": "app",
6 | "installMode": "prefetch",
7 | "resources": {
8 | "files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"]
9 | }
10 | },
11 | {
12 | "name": "assets",
13 | "installMode": "lazy",
14 | "updateMode": "prefetch",
15 | "resources": {
16 | "files": ["/assets/**"]
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/batch/actions.ts:
--------------------------------------------------------------------------------
1 | import { Action } from 'app/modules/editor/store';
2 |
3 | export enum BatchActionTypes {
4 | BatchAction = '__batch__BATCH',
5 | }
6 |
7 | export class BatchAction implements Action {
8 | readonly type = BatchActionTypes.BatchAction;
9 | readonly payload: ReadonlyArray;
10 | constructor(...actions: Action[]) {
11 | this.payload = actions;
12 | }
13 | }
14 |
15 | export type BatchActions = BatchAction;
16 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_pencil.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_zoompan.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/demos/index.ts:
--------------------------------------------------------------------------------
1 | export interface DemoInfo {
2 | readonly id: string;
3 | readonly title: string;
4 | }
5 |
6 | export const DEMO_INFOS: ReadonlyArray = [
7 | { id: 'playtopause', title: 'Play-to-pause' },
8 | { id: 'searchtoclose', title: 'Search-to-close' },
9 | { id: 'morphinganimals', title: 'Morphing animals' },
10 | { id: 'visibilitystrike', title: 'Visibility strike' },
11 | { id: 'heartbreak', title: 'Heart break' },
12 | ];
13 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Shape Shifter",
3 | "short_name": "ShapeShifter",
4 | "theme_color": "#607d8b",
5 | "background_color": "#e0e0e0",
6 | "display": "standalone",
7 | "description": "Shape Shifter is a web-app that simplifies the process of creating SVG-based path morphing animations.",
8 | "icons": [{
9 | "src": "assets/shapeshifter.png",
10 | "sizes": "600x600",
11 | "type": "image/png"
12 | }],
13 | "scope": "./",
14 | "start_url": "./"
15 | }
16 |
--------------------------------------------------------------------------------
/src/typings/paper/HitOptions.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'paper' {
2 | export interface HitOptions {
3 | tolerance?: number;
4 | class?: Constructor;
5 | fill?: boolean;
6 | stroke?: boolean;
7 | segments?: boolean;
8 | curves?: boolean;
9 | handles?: boolean;
10 | ends?: boolean;
11 | bounds?: boolean;
12 | center?: boolean;
13 | guides?: boolean;
14 | selected?: boolean;
15 | match?: (hitResult: HitResult) => boolean;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/assets/tools/tool_ellipse.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/root/_root-theme.scss:
--------------------------------------------------------------------------------
1 | @mixin ss-root-theme($theme) {
2 | $background: map-get($theme, ss-background);
3 | $accent: map-get($theme, accent);
4 | div.display-container {
5 | background-color: mat-color($background, base300);
6 | }
7 | .file-drop-target {
8 | &.is-dragging-over::after {
9 | background-color: mat-color($accent, darker, 0.5);
10 | box-shadow: 0 0 0 8px mat-color($accent, darker) inset;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/theme/actions.ts:
--------------------------------------------------------------------------------
1 | import { Action } from 'app/modules/editor/store';
2 |
3 | import { ThemeType } from './reducer';
4 |
5 | export enum ThemeActionTypes {
6 | SetTheme = '__theme__SET_THEME',
7 | }
8 |
9 | export class SetTheme implements Action {
10 | readonly type = ThemeActionTypes.SetTheme;
11 | readonly payload: { themeType: ThemeType };
12 | constructor(themeType: ThemeType) {
13 | this.payload = { themeType };
14 | }
15 | }
16 |
17 | export type ThemeActions = SetTheme;
18 |
--------------------------------------------------------------------------------
/src/app/modules/editor/services/snackbar.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { MatSnackBar } from '@angular/material';
3 |
4 | export enum Duration {
5 | Short = 2750,
6 | Long = 5000,
7 | }
8 |
9 | @Injectable({ providedIn: 'root' })
10 | export class SnackBarService {
11 | constructor(private readonly snackBar: MatSnackBar) {}
12 |
13 | show(message: string, action = '', duration = Duration.Short) {
14 | this.snackBar.open(message, action.toUpperCase(), { duration });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "files.exclude": {
4 | "node_modules/**": true,
5 | "**/*~": true,
6 | "**/*.js": {
7 | "when": "$(basename).ts"
8 | },
9 | "**/*.js.map": {
10 | "when": "$(basename)"
11 | }
12 | },
13 | "files.trimTrailingWhitespace": true,
14 | "html.format.wrapAttributes": "force",
15 | "prettier.printWidth": 100,
16 | "prettier.singleQuote": true,
17 | "prettier.tabWidth": 2,
18 | "typescript.tsdk": "node_modules/typescript/lib"
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/index.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | // By default paper.js bakes matrix transformations directly into its children.
4 | // This is usually not the behavior we want (especially for groups).
5 | paper.settings.applyMatrix = false;
6 |
7 | // By default paper.js automatically inserts newly created items into the active layer.
8 | // This behavior makes it harder to explicitly position things in the item hierarchy.
9 | paper.settings.insertItems = false;
10 |
11 | export { PaperProject } from './PaperProject';
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/common/MathUtil.spec.ts:
--------------------------------------------------------------------------------
1 | import { MathUtil, Matrix } from '.';
2 |
3 | describe('MathUtil', () => {
4 | it('#transformPoint', () => {
5 | const point = { x: 1, y: 1 };
6 | const matrix = Matrix.identity();
7 | const transformed = MathUtil.transformPoint(point, matrix);
8 | expect(transformed).toEqual({ x: 1, y: 1 });
9 | });
10 |
11 | it('#areCollinear', () => {
12 | expect(MathUtil.areCollinear({ x: 16, y: 6 }, { x: 14, y: 5 }, { x: 19, y: 20 })).toEqual(
13 | false,
14 | );
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "paths": {
6 | "src/*": ["../src/*"],
7 | "os": ["../node_modules/os-browserify/browser.js"],
8 | "stream": ["../node_modules/stream-browserify/index.js"],
9 | "jszip": ["../node_modules/jszip/dist/jszip.min.js"],
10 | "paper": ["../node_modules/paper/dist/paper-core.min.js"]
11 | },
12 | "baseUrl": "./",
13 | "module": "es2015"
14 | },
15 | "exclude": ["test.ts", "**/*.spec.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/mixins/DestroyableMixin.ts:
--------------------------------------------------------------------------------
1 | import { OnDestroy } from '@angular/core';
2 | import { Subscription } from 'rxjs';
3 |
4 | export function DestroyableMixin(Base = class {} as T) {
5 | return class extends Base implements OnDestroy {
6 | private readonly subscriptions: Subscription[] = [];
7 |
8 | protected registerSubscription(sub: Subscription) {
9 | this.subscriptions.push(sub);
10 | }
11 |
12 | ngOnDestroy() {
13 | this.subscriptions.forEach(x => x.unsubscribe());
14 | }
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/src/assets/icons/addlayer.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/batch/metareducer.ts:
--------------------------------------------------------------------------------
1 | import { ActionReducer } from 'app/modules/editor/store';
2 | import { EditorState } from 'app/modules/editor/store/reducer';
3 |
4 | import { BatchActionTypes, BatchActions } from './actions';
5 |
6 | export function metaReducer(reducer: ActionReducer): ActionReducer {
7 | return (state: EditorState, action: BatchActions) => {
8 | const isBatchAction = action.type === BatchActionTypes.BatchAction;
9 | return (isBatchAction ? action.payload : [action]).reduce(reducer, state);
10 | };
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/properties/FractionProperty.ts:
--------------------------------------------------------------------------------
1 | import { NumberConfig, NumberProperty } from './NumberProperty';
2 |
3 | export class FractionProperty extends NumberProperty {
4 | constructor(name: string, config: NumberConfig = {}) {
5 | super(name, {
6 | isAnimatable: config.isAnimatable,
7 | min: 0,
8 | max: 1,
9 | isInteger: false,
10 | });
11 | }
12 |
13 | // @Override
14 | getAnimatorValueType() {
15 | return 'floatType';
16 | }
17 |
18 | // @Override
19 | getTypeName() {
20 | return 'FractionProperty';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/typings/paper/PlacedSymbol.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'paper' {
2 | /**
3 | * A PlacedSymbol represents an instance of a symbol which has been placed in a Paper.js project.
4 | */
5 | export class PlacedSymbol extends Item {
6 | /**
7 | * Creates a new PlacedSymbol Item.
8 | * @param symbol - the symbol to place
9 | * @param point [optional] - the center point of the placed symbol
10 | */
11 | constructor(symbol: Symbol, point?: Point);
12 |
13 | /**
14 | * The symbol that the placed symbol refers to.
15 | */
16 | symbol: Symbol;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/bugsnag/index.ts:
--------------------------------------------------------------------------------
1 | import BugsnagErrorHandler from 'bugsnag-angular';
2 | import bugsnag from 'bugsnag-js';
3 | import { environment } from 'environments/environment';
4 | import { version } from 'environments/version';
5 |
6 | export const bugsnagClient = bugsnag({
7 | apiKey: 'd662c2c8a7e13ac94f67e81e26bf3a4e',
8 | appVersion: version,
9 | releaseStage: environment.production ? 'production' : 'development',
10 | notifyReleaseStages: ['production'],
11 | });
12 |
13 | export function errorHandlerFactory() {
14 | return new BugsnagErrorHandler(bugsnagClient);
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/modules/editor/services/StoreUtil.ts:
--------------------------------------------------------------------------------
1 | import { ToolMode } from 'app/modules/editor/model/paper';
2 | import {
3 | SetEditPathInfo,
4 | SetRotateItemsInfo,
5 | SetToolMode,
6 | SetTransformPathsInfo,
7 | } from 'app/modules/editor/store/paper/actions';
8 |
9 | // TODO: expand on this class... possibly a better redesigned version?
10 |
11 | export function getEnterDefaultModeActions() {
12 | return [
13 | new SetToolMode(ToolMode.Default),
14 | new SetEditPathInfo(undefined),
15 | new SetRotateItemsInfo(undefined),
16 | new SetTransformPathsInfo(undefined),
17 | ];
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/properties/NameProperty.ts:
--------------------------------------------------------------------------------
1 | import { Property } from './Property';
2 |
3 | export class NameProperty extends Property {
4 | static sanitize(value = '') {
5 | return value
6 | .toLowerCase()
7 | .replace(/^\s+|\s+$/g, '')
8 | .replace(/[\s-]+/g, '_')
9 | .replace(/[^\w_]+/g, '');
10 | }
11 |
12 | // @Override
13 | setEditableValue(model: any, propertyName: string, value: string) {
14 | model[propertyName] = NameProperty.sanitize(value);
15 | }
16 |
17 | // @Override
18 | getTypeName() {
19 | return 'NameProperty';
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/modules/editor/services/index.ts:
--------------------------------------------------------------------------------
1 | export { ActionModeService } from './actionmode.service';
2 | export { ClipboardService } from './clipboard.service';
3 | export { FileExportService } from './fileexport.service';
4 | export { FileImportService } from './fileimport.service';
5 | export { LayerTimelineService } from './layertimeline.service';
6 | export { PlaybackService } from './playback.service';
7 | export { SnackBarService } from './snackbar.service';
8 | export { ShortcutService } from './shortcut.service';
9 | export { ThemeService } from './theme.service';
10 | export { PaperService } from './paper.service';
11 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/item/EditPathRaster.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | export class EditPathRaster extends paper.Raster {
4 | constructor(
5 | readonly type: 'segment' | 'handle-in' | 'handle-out',
6 | readonly segmentIndex: number,
7 | readonly isSelected: boolean,
8 | center: paper.Point,
9 | ) {
10 | super(
11 | type === 'segment'
12 | ? `/assets/paper/${isSelected ? 'vector-segment-selected' : 'vector-segment'}.png`
13 | : `/assets/paper/${isSelected ? 'vector-handle-selected' : 'vector-handle'}.png`,
14 | center,
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/storefreeze/metareducer.ts:
--------------------------------------------------------------------------------
1 | import { Action, ActionReducer } from 'app/modules/editor/store';
2 | import * as deepFreeze from 'deep-freeze-strict';
3 |
4 | /**
5 | * Meta reducer that prevents state from being mutated anywhere in the app.
6 | */
7 | export function metaReducer(reducer: ActionReducer): ActionReducer {
8 | return (state: T, action: Action) => {
9 | if (state) {
10 | deepFreeze(state);
11 | }
12 | const nextState = reducer(state, action);
13 | if (nextState) {
14 | deepFreeze(nextState);
15 | }
16 | return nextState;
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 | sudo: required
3 | language: node_js
4 | node_js:
5 | - "9.10.1"
6 | os:
7 | - linux
8 | env:
9 | global:
10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null
11 | - DISPLAY=:99.0
12 | - CHROME_BIN=chromium-browser
13 | before_script:
14 | - sh -e /etc/init.d/xvfb start
15 | install:
16 | - npm install
17 | script:
18 | - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then precise-commits --check-only --head=$TRAVIS_PULL_REQUEST_SHA --base=$(git merge-base HEAD $TRAVIS_BRANCH); fi'
19 | - npm run lint
20 | - npm run test-once
21 | - npm run build
22 | after_success:
23 | - npm run coveralls
24 |
--------------------------------------------------------------------------------
/src/app/modules/editor/components/splashscreen/splashscreen.component.scss:
--------------------------------------------------------------------------------
1 | @import '~@angular/material/theming';
2 | :host {
3 | position: absolute;
4 | left: 0;
5 | top: 0;
6 | right: 0;
7 | bottom: 0;
8 | user-select: none;
9 | background-color: mat-color(mat-palette($mat-grey, 300));
10 | }
11 |
12 | .splashscreen-logo {
13 | width: 144px;
14 | height: 144px;
15 | margin-bottom: 16px;
16 | }
17 |
18 | .splashscreen-text {
19 | font-size: 18px;
20 | line-height: 22px;
21 | padding-left: 16px;
22 | padding-right: 16px;
23 | padding-bottom: 16px;
24 | text-align: center;
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/item/RotateItemsPivotRaster.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | export class RotateItemsPivotRaster extends paper.Raster {
4 | private static instance: RotateItemsPivotRaster;
5 |
6 | static of(position: paper.Point) {
7 | if (!RotateItemsPivotRaster.instance) {
8 | RotateItemsPivotRaster.instance = new RotateItemsPivotRaster();
9 | }
10 | const raster = RotateItemsPivotRaster.instance.clone(false) as RotateItemsPivotRaster;
11 | raster.position = position;
12 | return raster;
13 | }
14 |
15 | constructor() {
16 | super('/assets/paper/rotate-items-pivot.png');
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/assets/icons/grouplayer.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/layers/selectors.ts:
--------------------------------------------------------------------------------
1 | import { createDeepEqualSelector, getEditorState } from 'app/modules/editor/store/selectors';
2 | import { createSelector } from 'reselect';
3 |
4 | const getLayerState = createSelector(getEditorState, s => s.layers);
5 | export const getVectorLayer = createSelector(getLayerState, l => l.vectorLayer);
6 | export const getSelectedLayerIds = createDeepEqualSelector(getLayerState, l => l.selectedLayerIds);
7 | export const getCollapsedLayerIds = createDeepEqualSelector(
8 | getLayerState,
9 | l => l.collapsedLayerIds,
10 | );
11 | export const getHiddenLayerIds = createDeepEqualSelector(getLayerState, l => l.hiddenLayerIds);
12 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/tool/Tool.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | /** Represents the base class for all tool types. */
4 | export abstract class Tool {
5 | /** Called immediately after this tool has been activated. */
6 | onActivate() {}
7 |
8 | /**
9 | * Called when this tool has received a tool event (i.e. mouse down,
10 | * mouse drag, mouse move, mouse up).
11 | */
12 | onToolEvent(event: paper.ToolEvent) {}
13 |
14 | /** Called when this tool has received a key event (i.e. key down, key up). */
15 | onKeyEvent(event: paper.KeyEvent) {}
16 |
17 | /** Called immediately after this tool has been deactivated. */
18 | onDeactivate() {}
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 |
10 | # IDEs and editors
11 | /.idea
12 | .project
13 | .classpath
14 | .c9/
15 | *.launch
16 | .settings/
17 |
18 | # IDE - VSCode
19 | .vscode/*
20 | !.vscode/settings.json
21 | !.vscode/tasks.json
22 | !.vscode/launch.json
23 | !.vscode/extensions.json
24 |
25 | # misc
26 | /.sass-cache
27 | /connect.lock
28 | /coverage/*
29 | /libpeerconnection.log
30 | npm-debug.log
31 | testem.log
32 | /typings
33 |
34 | # e2e
35 | /e2e/*.js
36 | /e2e/*.map
37 |
38 | #System Files
39 | .DS_Store
40 | Thumbs.db
41 |
42 | *~
43 | *.sublime-workspace
44 |
--------------------------------------------------------------------------------
/src/assets/icons/collection.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/app/modules/editor/store/reset/reducer.ts:
--------------------------------------------------------------------------------
1 | import { ResetActionTypes, ResetActions } from './actions';
2 |
3 | // TODO: remove this 'isBeingReset' flag... see TODO in layer timeline component
4 | export interface State {
5 | readonly isBeingReset: boolean;
6 | }
7 |
8 | export function buildInitialState() {
9 | return {
10 | isBeingReset: false,
11 | } as State;
12 | }
13 |
14 | export function reducer(state = buildInitialState(), action: ResetActions) {
15 | if (action.type === ResetActionTypes.ResetWorkspace) {
16 | return { ...state, isBeingReset: true };
17 | }
18 | const { isBeingReset } = state;
19 | if (isBeingReset) {
20 | return { ...state, isBeingReset: false };
21 | }
22 | return state;
23 | }
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "baseUrl": "src",
6 | "paths": {
7 | "src/*": ["./src/*"]
8 | },
9 | "sourceMap": true,
10 | "declaration": false,
11 | "moduleResolution": "node",
12 | "emitDecoratorMetadata": true,
13 | "experimentalDecorators": true,
14 | "noImplicitReturns": true,
15 | "noImplicitAny": true,
16 | "noUnusedLocals": false,
17 | "noUnusedParameters": false,
18 | "importHelpers": true,
19 | "target": "es5",
20 | "typeRoots": ["node_modules/@types"],
21 | "lib": ["es2017", "dom"]
22 | },
23 | "angularCompilerOptions": {
24 | "preserveWhitespaces": false
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/Gesture.ts:
--------------------------------------------------------------------------------
1 | import * as paper from 'paper';
2 |
3 | /**
4 | * A gesture represents a user interaction with the mouse or keyboard. Typically
5 | * a gesture is used in one of two ways:
6 | *
7 | * (1) To monitor the state of events that occurs between the initial
8 | * mouse down through the final mouse up.
9 | *
10 | * (2) To monitor mouse move events and react accordingly.
11 | */
12 | export abstract class Gesture {
13 | onMouseDown(event: paper.ToolEvent) {}
14 | onMouseDrag(event: paper.ToolEvent) {}
15 | onMouseMove(event: paper.ToolEvent) {}
16 | onMouseUp(event: paper.ToolEvent) {}
17 | onKeyDown(event: paper.KeyEvent) {}
18 | onKeyUp(event: paper.KeyEvent) {}
19 | }
20 |
--------------------------------------------------------------------------------
/src/assets/icons/animationblock.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/icons/vectorlayer.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/app/modules/editor/scripts/paper/gesture/select/DeselectItemGesture.ts:
--------------------------------------------------------------------------------
1 | import { Gesture } from 'app/modules/editor/scripts/paper/gesture';
2 | import { PaperService } from 'app/modules/editor/services';
3 | import * as paper from 'paper';
4 |
5 | /**
6 | * A gesture that deselects a single item.
7 | *
8 | * Preconditions:
9 | * - The user is in default mode.
10 | */
11 | export class DeselectItemGesture extends Gesture {
12 | constructor(private readonly ps: PaperService, private readonly deselectedItemId: string) {
13 | super();
14 | }
15 |
16 | // @Override
17 | onMouseDown(event: paper.ToolEvent) {
18 | const layerIds = new Set(this.ps.getSelectedLayerIds());
19 | layerIds.delete(this.deselectedItemId);
20 | this.ps.setSelectedLayerIds(layerIds);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/modules/editor/model/properties/EnumProperty.ts:
--------------------------------------------------------------------------------
1 | import * as _ from 'lodash';
2 |
3 | import { Property } from './Property';
4 |
5 | export class EnumProperty extends Property {
6 | constructor(name: string, readonly options: ReadonlyArray