From 2ec546820f22615e1a4903b8c6469a16911a25df Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 10 Dec 2019 11:35:56 +0100 Subject: [PATCH 01/67] build(dep): `@babylonjs` & `@types/node`: - @babylonjs:4.1.0-beta.9 - @types/node:12.12.16 --- package.json | 10 +++--- yarn.lock | 98 ++++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index f07b02f3..46a607f2 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "@angular/platform-browser": "8.2.14", "@angular/platform-browser-dynamic": "8.2.14", "@angular/router": "8.2.14", - "@babylonjs/core": "4.1.0-beta.3", - "@babylonjs/materials": "4.1.0-beta.3", + "@babylonjs/core": "4.1.0-beta.9", + "@babylonjs/materials": "4.1.0-beta.9", "@ngrx/store": "8.5.2", "@nrwl/angular": "8.9.0", "core-js": "3.4.8", @@ -59,15 +59,15 @@ "@angular/cli": "8.3.20", "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", - "@babylonjs/inspector": "4.1.0-beta.3", + "@babylonjs/inspector": "4.1.0-beta.9", "@nrwl/cypress": "8.9.0", "@nrwl/jest": "8.9.0", "@nrwl/node": "8.9.0", "@nrwl/workspace": "8.9.0", "@types/benchmark": "1.0.31", "@types/jest": "24.0.23", - "@types/node": "12.12.14", - "babylonjs": "4.1.0-beta.3", + "@types/node": "12.12.16", + "babylonjs": "4.1.0-beta.9", "benchmark": "2.1.4", "codelyzer": "5.2.0", "cypress": "3.7.0", diff --git a/yarn.lock b/yarn.lock index bfaa5e9b..d0046519 100644 --- a/yarn.lock +++ b/yarn.lock @@ -914,58 +914,58 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babylonjs/core@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.3.tgz#7020ad6c3ef4a891f305ba337e6bc4dc49338f14" - integrity sha512-ibHPUfGlRRtmh6IezCpXutvfnxL4/iW3oHV/M/92m47mZApBsQWmLCrLsN3C4W+fbSWJqCw9fggBdrOzThLRpA== +"@babylonjs/core@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.9.tgz#e77c3ddde0354b305aab0f234a7c4901914c8ae4" + integrity sha512-8jluf2f0ip+abcWNZn01eONB4joFR2lFWbpIk6L4x9lu/H5eENUT4WKqJ+1zFSKz2mWi0VJBu2snojC+I6JRKw== dependencies: tslib "^1.10.0" -"@babylonjs/gui@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.3.tgz#35d22696753562fcfb09c51582fca4e3be6569dc" - integrity sha512-YYXfrtIhSLpCN5P6hYH06+2gy4m3k/PsYqW9lbgCrzihCqBJ78JiymIbnq5+SeylbyHYsXbnlyMTkUw0lyRjiw== +"@babylonjs/gui@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.9.tgz#7668b1b6a04e952e40a9d2b0ecab8742cf7e7e1e" + integrity sha512-bm3Bq+Ldy+n1jIkBCg/4cCxGV0zJe6uGQ2wLxtMqL2xVgBDO6rIdLCZBEFMeAjs/18d0ceNeONk8kLhVEtiLSQ== dependencies: - "@babylonjs/core" "4.1.0-beta.3" + "@babylonjs/core" "4.1.0-beta.9" tslib "^1.10.0" -"@babylonjs/inspector@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.3.tgz#c9b60c69ee5f1f28eaa921473665e924ec2c07c4" - integrity sha512-eoZIWegmysN7EQVCvNzTsNLG1Ozz5kicI0UUJLTbwzJhOWC+6YXXlE0rlCXOXg6Bk5J8aRs40gdKJLSGG7RItQ== - dependencies: - "@babylonjs/core" "4.1.0-beta.3" - "@babylonjs/gui" "4.1.0-beta.3" - "@babylonjs/loaders" "4.1.0-beta.3" - "@babylonjs/materials" "4.1.0-beta.3" - "@babylonjs/serializers" "4.1.0-beta.3" - babylonjs-gltf2interface "4.1.0-beta.3" +"@babylonjs/inspector@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.9.tgz#dfd0ec78180dabe569bb16702f2dcef572557f40" + integrity sha512-6tT+rc3UMdKiNugYNAJxBP5Zza+2ABLgscCc5VG8rDGap0i6x/6aPoYEvZ0iGNQCrjvS66kd5/vVtCyoc+ISuQ== + dependencies: + "@babylonjs/core" "4.1.0-beta.9" + "@babylonjs/gui" "4.1.0-beta.9" + "@babylonjs/loaders" "4.1.0-beta.9" + "@babylonjs/materials" "4.1.0-beta.9" + "@babylonjs/serializers" "4.1.0-beta.9" + babylonjs-gltf2interface "4.1.0-beta.9" tslib "^1.10.0" -"@babylonjs/loaders@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.3.tgz#b391d2dab93a949a7d14bd341373794f91c35347" - integrity sha512-VmjEp+DfuVZYvJsfPDIwQz+WNFMk4sxNH5CnnUq9AnrYeqoagSiIkN2mLQJWKyU/bcH1UzN8VCPvjdfj9nte7w== +"@babylonjs/loaders@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.9.tgz#33582c15ec144403db2cf1e614ac4c26d11e185f" + integrity sha512-0QPDIzaAxe3UOK/vzz4EPrH90CGO8cYJS5ev74sySwsodTkEDCgcyBuGsJYNQic1yje2SWrcBUWfaVCm/8QcYA== dependencies: - "@babylonjs/core" "4.1.0-beta.3" - babylonjs-gltf2interface "4.1.0-beta.3" + "@babylonjs/core" "4.1.0-beta.9" + babylonjs-gltf2interface "4.1.0-beta.9" tslib "^1.10.0" -"@babylonjs/materials@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.3.tgz#b3aaacfb59a74ef52d745629219a30febc6fab5c" - integrity sha512-9R4QrwBvoFB7ER25+vo71eSJjT+2wReJ+BwZ2NEy/VRLYrSJ1E7RUNdZ1RfGnI9CZHbh4qBN2G3zFG0ycNjlcQ== +"@babylonjs/materials@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.9.tgz#4ca9601bdb61338f3b0dc874a5ccaff9a9b3a37c" + integrity sha512-NBYMHtgPSm2BZn9FcUgeb4eVJXForv4sR2gt6UKBdAUeA8AXoJc5fATQEwybEFwGMDafB1XFfP7bIxCBJy/jMg== dependencies: - "@babylonjs/core" "4.1.0-beta.3" + "@babylonjs/core" "4.1.0-beta.9" tslib "^1.10.0" -"@babylonjs/serializers@4.1.0-beta.3": - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.3.tgz#1966153ab7b11da1d1d13c2b63b3df3bf5d0701a" - integrity sha512-OR+YUiWrKSdibgBURa/VuRlle2Vgih2+dQ6ZKSdDZrxvtPcaKukwzzBw9GmIzIU6G377GPHJSQnTNQkBbllV2Q== +"@babylonjs/serializers@4.1.0-beta.9": + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.9.tgz#f92db8df538e0e823bf68a69c4a4f684a889b6bf" + integrity sha512-ai92CPa48Q1aUxfVN/bLIoTfWssPeEFojs2eTwox8CnipcI4Njl7qGyT9FQRoe1AvmGpn6GR4baXawj4WPQnpQ== dependencies: - "@babylonjs/core" "4.1.0-beta.3" - babylonjs-gltf2interface "4.1.0-beta.3" + "@babylonjs/core" "4.1.0-beta.9" + babylonjs-gltf2interface "4.1.0-beta.9" tslib "^1.10.0" "@cnakazawa/watch@^1.0.3": @@ -1422,10 +1422,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== -"@types/node@12.12.14": - version "12.12.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" - integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== +"@types/node@12.12.16": + version "12.12.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.16.tgz#3ebcbd7bf978fa4c5120fee8be57083271a8b3ac" + integrity sha512-vRuMyoOr5yfNf8QWxXegOjeyjpWJxFePzHzmBOIzDIzo+rSqF94RW0PkS6y4T2+VjAWLXHWrfbIJY3E3aS7lUw== "@types/parse-json@^4.0.0": version "4.0.0" @@ -2212,15 +2212,15 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -babylonjs-gltf2interface@4.1.0-beta.3: - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.3.tgz#58bf0542f90dec2bd3e9fcc825a5964af9d54c1b" - integrity sha512-4TNaZLr/l6H3Ib6OpX7qOfDMM8XMS0XBeH62NDm7FOKrSRRQww4ait0AqewHNhNfymakunLgRbO4nrlEf4tC/A== +babylonjs-gltf2interface@4.1.0-beta.9: + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.9.tgz#43238e5ac6b2d84554a9b99527fc626c160d0fce" + integrity sha512-aTsoK6cLBVguU5DlgBvRbiti4G5ItumbnYbLvcQr5IbG9xuPeca01N70QxTB1OWjNiGkq0+tlIqsrQg3J9xBgQ== -babylonjs@4.1.0-beta.3: - version "4.1.0-beta.3" - resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.3.tgz#34fb13ec6377419f50a0fe8f7d199b4a31b7e917" - integrity sha512-9C+AKJPWJmLN0azP5p4WwjsSA8YmEpUh52Tf/lD4OBOk2cBXHOk+LwYAxZAX8X98tAQvNjjw5uXeyNVVh+OYYw== +babylonjs@4.1.0-beta.9: + version "4.1.0-beta.9" + resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.9.tgz#1d2345ce0b17917383c31f64072fea8b89cbb94a" + integrity sha512-5B8+ESAc1WsdOjfml0Amm8SVdSeCLv6HFmcVxQZCE6ftNhNvN+UkN+OILTIZ9LvdPoslOntY/Ow7PNAyIZ/vSw== bail@^1.0.0: version "1.0.4" From 7d237f1cb0890156be1846efd47f51f352a3b3eb Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 10 Dec 2019 15:23:21 +0100 Subject: [PATCH 02/67] feat(apps/frontend): select initial tool --- apps/frontend/src/app/app.reducer.ts | 14 +++++++++++++- .../app/tools-panel/tools-panel.component.ts | 17 +++++++++++++---- .../src/app/tools-panel/tools-panel.module.ts | 3 ++- .../src/app/tools-panel/tools-panel.reducer.ts | 2 +- libs/ui/src/lib/toolbar/toolbar.component.ts | 4 +++- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/apps/frontend/src/app/app.reducer.ts b/apps/frontend/src/app/app.reducer.ts index 27de3751..30f4789e 100644 --- a/apps/frontend/src/app/app.reducer.ts +++ b/apps/frontend/src/app/app.reducer.ts @@ -1,5 +1,5 @@ import { InjectionToken } from '@angular/core'; -import { Action, ActionReducer, ActionReducerMap, MetaReducer } from '@ngrx/store'; +import { Action, ActionReducer, ActionReducerMap, createFeatureSelector, createSelector, MetaReducer } from '@ngrx/store'; import { environment } from '../environments/environment'; import * as fromToolsPanel from './tools-panel/tools-panel.reducer'; @@ -44,3 +44,15 @@ export function logger(reducer: ActionReducer): ActionReducer { * that will be composed to form the root meta-reducer. */ export const metaReducers: MetaReducer[] = !environment.production ? [logger] : []; + +/** + * ToolsPanel reducers + */ +export const selectToolsPanelState = createFeatureSelector( + fromToolsPanel.toolsPanelFeatureKey, +); + +export const selectSelectedToolId = createSelector( + selectToolsPanelState, + fromToolsPanel.selectSelectedToolId, +); diff --git a/apps/frontend/src/app/tools-panel/tools-panel.component.ts b/apps/frontend/src/app/tools-panel/tools-panel.component.ts index 7a0206af..3c84f224 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.component.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.component.ts @@ -1,18 +1,25 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { UiToolbarToolChange, UiToolbarToolConfig } from '@talus/ui'; +import { Observable } from 'rxjs'; +import * as fromApp from '../app.reducer'; import { Tool } from './tool.model'; import { selectTool } from './tools-panel.actions'; -import { State } from './tools-panel.reducer'; @Component({ selector: 'fe-tools-panel', template: ` - + `, changeDetection: ChangeDetectionStrategy.OnPush, }) export class ToolsPanelComponent { + private selectedToolId$: Observable; + tools: UiToolbarToolConfig[] = [ { icon: 'add_circle_outline', @@ -26,7 +33,9 @@ export class ToolsPanelComponent { }, ]; - constructor(private store: Store) {} + constructor(private store: Store) { + this.selectedToolId$ = store.pipe(select(fromApp.selectSelectedToolId)); + } onToolChange(event: UiToolbarToolChange): void { this.store.dispatch(selectTool({ id: event.value })); diff --git a/apps/frontend/src/app/tools-panel/tools-panel.module.ts b/apps/frontend/src/app/tools-panel/tools-panel.module.ts index 1b5030c6..55db8f76 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.module.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.module.ts @@ -1,10 +1,11 @@ +import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { ToolbarModule } from '@talus/ui'; import { ToolsPanelComponent } from './tools-panel.component'; @NgModule({ declarations: [ToolsPanelComponent], - imports: [ToolbarModule], + imports: [CommonModule, ToolbarModule], exports: [ToolsPanelComponent], }) export class ToolsPanelModule {} diff --git a/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts b/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts index b83337ad..134e1293 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts @@ -23,4 +23,4 @@ export const reducer = createReducer( }), ); -export const getSelectedToolId = (state: State) => state.selectedToolId; +export const selectSelectedToolId = (state: State) => state.selectedToolId; diff --git a/libs/ui/src/lib/toolbar/toolbar.component.ts b/libs/ui/src/lib/toolbar/toolbar.component.ts index ae4a6063..68e2f341 100644 --- a/libs/ui/src/lib/toolbar/toolbar.component.ts +++ b/libs/ui/src/lib/toolbar/toolbar.component.ts @@ -14,7 +14,7 @@ export interface UiToolbarToolChange extends MatButtonToggleChange { @Component({ selector: ' ui-toolbar', template: ` - + extends MatButtonToggleChange { export class ToolbarComponent { @Input() tools: UiToolbarToolConfig[]; + @Input() selectedToolId: any; + @Output() toolChange = new EventEmitter>(); onChange(event: UiToolbarToolChange): void { From b9a2b8e34138959ce9522d8965ca6d909ee25567 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 10 Dec 2019 15:31:42 +0100 Subject: [PATCH 03/67] fix(apps/frontend): import hammerjs --- apps/frontend/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/main.ts b/apps/frontend/src/main.ts index 5e9d3d57..c23e64f8 100644 --- a/apps/frontend/src/main.ts +++ b/apps/frontend/src/main.ts @@ -1,6 +1,6 @@ import { enableProdMode, ViewEncapsulation } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - +import 'hammerjs'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; From 05ec1fa9b4073e7bb83426b9fca86cca88cc072b Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 10 Dec 2019 16:28:17 +0100 Subject: [PATCH 04/67] refactor(frontend): scene-viewer into container --- apps/frontend/src/app/app.component.spec.ts | 13 +++++-- apps/frontend/src/app/app.component.ts | 17 +-------- apps/frontend/src/app/app.module.ts | 5 +-- apps/frontend/src/app/app.reducer.ts | 9 ++++- .../src/app/scene-viewer-container/index.ts | 1 + .../scene-viewer-container.component.spec.ts | 36 +++++++++++++++++++ .../scene-viewer-container.component.ts | 25 +++++++++++++ .../scene-viewer-container.module.ts | 11 ++++++ .../tools-panel/tools-panel.component.spec.ts | 19 +++++++--- 9 files changed, 110 insertions(+), 26 deletions(-) create mode 100644 apps/frontend/src/app/scene-viewer-container/index.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts diff --git a/apps/frontend/src/app/app.component.spec.ts b/apps/frontend/src/app/app.component.spec.ts index 4c60af0d..4605e2a5 100644 --- a/apps/frontend/src/app/app.component.spec.ts +++ b/apps/frontend/src/app/app.component.spec.ts @@ -5,6 +5,13 @@ import { RouterTestingModule } from '@angular/router/testing'; import { SceneViewerTestModule, SidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; +@Component({ + selector: 'fe-scene-viewer-container', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class SceneViewerContainerStubComponent {} + @Component({ selector: 'fe-tools-panel', template: '', @@ -15,7 +22,7 @@ class ToolsPanelStubComponent {} describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [AppComponent, ToolsPanelStubComponent], + declarations: [AppComponent, SceneViewerContainerStubComponent, ToolsPanelStubComponent], imports: [ BrowserAnimationsModule, RouterTestingModule, @@ -43,6 +50,8 @@ describe('AppComponent', () => { const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('ui-sidenav-shell-left > fe-tools-panel')).not.toBeNull(); - expect(compiled.querySelector('ui-sidenav-shell-content > ui-scene-viewer')).not.toBeNull(); + expect( + compiled.querySelector('ui-sidenav-shell-content > fe-scene-viewer-container'), + ).not.toBeNull(); }); }); diff --git a/apps/frontend/src/app/app.component.ts b/apps/frontend/src/app/app.component.ts index 7816bc19..a5ef2d16 100644 --- a/apps/frontend/src/app/app.component.ts +++ b/apps/frontend/src/app/app.component.ts @@ -1,7 +1,4 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh'; -// import '@babylonjs/core/Rendering/edgesRenderer'; -import '@babylonjs/core/Rendering/outlineRenderer'; @Component({ selector: 'fe-root', @@ -16,10 +13,7 @@ import '@babylonjs/core/Rendering/outlineRenderer'; - + `, @@ -27,13 +21,4 @@ import '@babylonjs/core/Rendering/outlineRenderer'; }) export class AppComponent { title = 'frontend'; - - onPointerPick(pointerEvent: PointerEvent): void { - console.log(pointerEvent.button); - } - - onMeshPick(mesh: AbstractMesh): void { - // mesh.edgesRenderer ? mesh.disableEdgesRendering() : mesh.enableEdgesRendering(); - mesh.renderOutline = !mesh.renderOutline; - } } diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts index d21be000..2238a7d0 100644 --- a/apps/frontend/src/app/app.module.ts +++ b/apps/frontend/src/app/app.module.ts @@ -3,9 +3,10 @@ import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterModule } from '@angular/router'; import { StoreModule } from '@ngrx/store'; -import { SceneViewerModule, SidenavShellModule } from '@talus/ui'; +import { SidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; import { metaReducers, ROOT_REDUCERS } from './app.reducer'; +import { SceneViewerContainerModule } from './scene-viewer-container'; import { ToolsPanelModule } from './tools-panel/tools-panel.module'; @NgModule({ @@ -31,8 +32,8 @@ import { ToolsPanelModule } from './tools-panel/tools-panel.module'; }, }), + SceneViewerContainerModule, SidenavShellModule, - SceneViewerModule, ToolsPanelModule, ], providers: [], diff --git a/apps/frontend/src/app/app.reducer.ts b/apps/frontend/src/app/app.reducer.ts index 30f4789e..eae008a3 100644 --- a/apps/frontend/src/app/app.reducer.ts +++ b/apps/frontend/src/app/app.reducer.ts @@ -1,5 +1,12 @@ import { InjectionToken } from '@angular/core'; -import { Action, ActionReducer, ActionReducerMap, createFeatureSelector, createSelector, MetaReducer } from '@ngrx/store'; +import { + Action, + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer, +} from '@ngrx/store'; import { environment } from '../environments/environment'; import * as fromToolsPanel from './tools-panel/tools-panel.reducer'; diff --git a/apps/frontend/src/app/scene-viewer-container/index.ts b/apps/frontend/src/app/scene-viewer-container/index.ts new file mode 100644 index 00000000..d3c844a4 --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/index.ts @@ -0,0 +1 @@ +export { SceneViewerContainerModule } from './scene-viewer-container.module'; diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts new file mode 100644 index 00000000..b5a1d43c --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -0,0 +1,36 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { SceneViewerContainerComponent } from './scene-viewer-container.component'; + +@Component({ + // tslint:disable-next-line:component-selector + selector: 'ui-scene-viewer', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class SceneViewerStubComponent {} + +describe('SceneViewerContainerComponent', () => { + let component: SceneViewerContainerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [SceneViewerContainerComponent, SceneViewerStubComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SceneViewerContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should render child component', () => { + fixture = TestBed.createComponent(SceneViewerContainerComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + + expect(compiled.querySelector('ui-scene-viewer')).not.toBeNull(); + }); +}); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts new file mode 100644 index 00000000..8708ff2b --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh'; +// import '@babylonjs/core/Rendering/edgesRenderer'; +import '@babylonjs/core/Rendering/outlineRenderer'; + +@Component({ + selector: 'fe-scene-viewer-container', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SceneViewerContainerComponent { + onPointerPick(pointerEvent: PointerEvent): void { + console.log(pointerEvent.button); + } + + onMeshPick(mesh: AbstractMesh): void { + // mesh.edgesRenderer ? mesh.disableEdgesRendering() : mesh.enableEdgesRendering(); + mesh.renderOutline = !mesh.renderOutline; + } +} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts new file mode 100644 index 00000000..6b7bf096 --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { SceneViewerModule } from '@talus/ui'; +import { SceneViewerContainerComponent } from './scene-viewer-container.component'; + +@NgModule({ + declarations: [SceneViewerContainerComponent], + imports: [CommonModule, SceneViewerModule], + exports: [SceneViewerContainerComponent], +}) +export class SceneViewerContainerModule {} diff --git a/apps/frontend/src/app/tools-panel/tools-panel.component.spec.ts b/apps/frontend/src/app/tools-panel/tools-panel.component.spec.ts index e917ccc1..8de556c9 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.component.spec.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.component.spec.ts @@ -1,9 +1,9 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Store } from '@ngrx/store'; -import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { MockStore } from '@ngrx/store/testing'; +import { ROOT_REDUCERS, State } from '../app.reducer'; import { ToolsPanelComponent } from './tools-panel.component'; import { ToolsPanelModule } from './tools-panel.module'; -import { initialState, State } from './tools-panel.reducer'; describe('ToolsPanelComponent', () => { let component: ToolsPanelComponent; @@ -14,8 +14,17 @@ describe('ToolsPanelComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [], - imports: [ToolsPanelModule], - providers: [provideMockStore({ initialState })], + imports: [ + ToolsPanelModule, + StoreModule.forRoot(ROOT_REDUCERS, { + runtimeChecks: { + strictStateImmutability: true, + strictActionImmutability: true, + strictStateSerializability: true, + strictActionSerializability: true, + }, + }), + ], }).compileComponents(); store = TestBed.get>(Store); From b2bd8ad0562f09797419c1d528b76a95300a440a Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 10 Dec 2019 17:11:41 +0100 Subject: [PATCH 05/67] feat(frontend): dispatch `pointerPick` action --- .../app/scene-viewer-container/pointer-button.model.ts | 10 ++++++++++ .../scene-viewer-container.actions.ts | 7 +++++++ .../scene-viewer-container.component.ts | 7 ++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts diff --git a/apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts b/apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts new file mode 100644 index 00000000..39afd4c3 --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts @@ -0,0 +1,10 @@ +/** + * https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button#Syntax + */ +export enum PointerButton { + Main = 0, // usually the left button or the un-initialized state + Auxiliary = 1, // usually the wheel button or the middle button (if present) + Secondary = 2, // usually the right button + Fourth = 3, // typically the Browser Back button + Fifth = 4, // typically the Browser Forward button +} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts new file mode 100644 index 00000000..3604a4f3 --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -0,0 +1,7 @@ +import { createAction, props } from '@ngrx/store'; +import { PointerButton } from './pointer-button.model'; + +export const pointerPick = createAction( + '[SceneViewerContainer] Pointer pick', + props<{ pointerButton: PointerButton }>(), +); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index 8708ff2b..eecc78bc 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -2,6 +2,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh'; // import '@babylonjs/core/Rendering/edgesRenderer'; import '@babylonjs/core/Rendering/outlineRenderer'; +import { Store } from '@ngrx/store'; +import * as fromApp from '../app.reducer'; +import { pointerPick } from './scene-viewer-container.actions'; @Component({ selector: 'fe-scene-viewer-container', @@ -14,8 +17,10 @@ import '@babylonjs/core/Rendering/outlineRenderer'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerContainerComponent { + constructor(private store: Store) {} + onPointerPick(pointerEvent: PointerEvent): void { - console.log(pointerEvent.button); + this.store.dispatch(pointerPick({ pointerButton: pointerEvent.button })); } onMeshPick(mesh: AbstractMesh): void { From ceee0135bd1cc0bbc6652b9713998635255dfc98 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 11 Dec 2019 13:03:08 +0100 Subject: [PATCH 06/67] feat(frontend): dispatch `add|removeVoxel` action --- .../scene-viewer-container.actions.ts | 15 ++-- .../scene-viewer-container.component.spec.ts | 69 +++++++++++++++++-- .../scene-viewer-container.component.ts | 50 ++++++++++---- libs/ui/src/lib/scene-viewer/index.ts | 2 + .../ui/src/lib/scene-viewer/pointer-button.ts | 0 .../scene-viewer/scene-viewer.component.ts | 1 - .../lib/scene-viewer/scene-viewer.service.ts | 26 +++++-- libs/vdb/src/lib/math/coord.ts | 4 ++ 8 files changed, 140 insertions(+), 27 deletions(-) rename apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts => libs/ui/src/lib/scene-viewer/pointer-button.ts (100%) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts index 3604a4f3..350c0e51 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -1,7 +1,14 @@ import { createAction, props } from '@ngrx/store'; -import { PointerButton } from './pointer-button.model'; +import { Coord } from '@talus/vdb'; -export const pointerPick = createAction( - '[SceneViewerContainer] Pointer pick', - props<{ pointerButton: PointerButton }>(), +const actionTypePrefix = '[SceneViewerContainer]'; + +export const addVoxel = createAction( + `${actionTypePrefix} Add voxel`, + props<{ position: Coord; value: number }>(), +); + +export const removeVoxel = createAction( + `${actionTypePrefix} Remove voxel`, + props<{ position: Coord }>(), ); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index b5a1d43c..3f3da356 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -1,5 +1,13 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Output } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { MemoizedSelector, Store } from '@ngrx/store'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { PointerButton, PointerPickInfo } from '@talus/ui'; +import { Subject } from 'rxjs'; +import * as fromApp from '../app.reducer'; +import { Tool } from '../tools-panel/tool.model'; +import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; import { SceneViewerContainerComponent } from './scene-viewer-container.component'; @Component({ @@ -8,29 +16,82 @@ import { SceneViewerContainerComponent } from './scene-viewer-container.componen template: '', changeDetection: ChangeDetectionStrategy.OnPush, }) -class SceneViewerStubComponent {} +class SceneViewerStubComponent { + @Output() pointerPick = new Subject(); +} describe('SceneViewerContainerComponent', () => { let component: SceneViewerContainerComponent; + let stubComponent: SceneViewerStubComponent; let fixture: ComponentFixture; + let mockStore: MockStore; + let mockSelectedToolIdSelector: MemoizedSelector; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [SceneViewerContainerComponent, SceneViewerStubComponent], + providers: [provideMockStore()], }).compileComponents(); + + mockStore = TestBed.get(Store); + spyOn(mockStore, 'dispatch'); + + mockSelectedToolIdSelector = mockStore.overrideSelector( + fromApp.selectSelectedToolId, + Tool.AddVoxel, + ); })); beforeEach(() => { fixture = TestBed.createComponent(SceneViewerContainerComponent); component = fixture.componentInstance; fixture.detectChanges(); + + stubComponent = fixture.debugElement.query(By.directive(SceneViewerStubComponent)) + .componentInstance; }); it('should render child component', () => { - fixture = TestBed.createComponent(SceneViewerContainerComponent); - fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('ui-scene-viewer')).not.toBeNull(); }); + + it('should dispatch no action if not PointerButton.Main', () => { + stubComponent.pointerPick.next({ + pickedPoint: [0, 0, 0], + pointerButton: PointerButton.Secondary, + normal: [0, 0, 0], + }); + + expect(mockStore.dispatch).not.toHaveBeenCalled(); + }); + + it('should dispatch `addVoxel` action', () => { + const action = addVoxel({ position: [1, 1, 2], value: 42 }); + + stubComponent.pointerPick.next({ + pickedPoint: [1, 1, 1], + pointerButton: PointerButton.Main, + normal: [0, 0, 1], + }); + + expect(mockStore.dispatch).toHaveBeenCalledWith(action); + }); + + it('should dispatch `removeVoxel` action', () => { + mockSelectedToolIdSelector.setResult(Tool.RemoveVoxel); + mockStore.refreshState(); + fixture.detectChanges(); + + const action = removeVoxel({ position: [1, 1, 1] }); + + stubComponent.pointerPick.next({ + pickedPoint: [1, 1, 1], + pointerButton: PointerButton.Main, + normal: [0, 0, 1], + }); + + expect(mockStore.dispatch).toHaveBeenCalledWith(action); + }); }); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index eecc78bc..0245d4e5 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -1,30 +1,56 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh'; // import '@babylonjs/core/Rendering/edgesRenderer'; -import '@babylonjs/core/Rendering/outlineRenderer'; -import { Store } from '@ngrx/store'; +// import '@babylonjs/core/Rendering/outlineRenderer'; +import { select, Store } from '@ngrx/store'; +import { PointerButton, PointerPickInfo } from '@talus/ui'; +import { add, Coord } from '@talus/vdb'; +import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; -import { pointerPick } from './scene-viewer-container.actions'; +import { Tool } from '../tools-panel/tool.model'; +import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; @Component({ selector: 'fe-scene-viewer-container', template: ` `, changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerContainerComponent { - constructor(private store: Store) {} + private selectedToolId$: Observable; - onPointerPick(pointerEvent: PointerEvent): void { - this.store.dispatch(pointerPick({ pointerButton: pointerEvent.button })); + constructor(private store: Store) { + this.selectedToolId$ = store.pipe(select(fromApp.selectSelectedToolId)); } - onMeshPick(mesh: AbstractMesh): void { - // mesh.edgesRenderer ? mesh.disableEdgesRendering() : mesh.enableEdgesRendering(); - mesh.renderOutline = !mesh.renderOutline; + onPointerPick(event: PointerPickInfo, selectedToolId: Tool): void { + this.dispatchPickAction(event, selectedToolId); + } + + // onMeshPick(mesh: AbstractMesh): void { + // mesh.edgesRenderer ? mesh.disableEdgesRendering() : mesh.enableEdgesRendering(); + // mesh.renderOutline = !mesh.renderOutline; + // } + + private dispatchPickAction(pickInfo: PointerPickInfo, selectedToolId: Tool): void { + if (pickInfo.pointerButton !== PointerButton.Main) { + return; + } + + switch (selectedToolId) { + case Tool.AddVoxel: + this.store.dispatch(addVoxel({ position: this.calcNewVoxelPosition(pickInfo), value: 42 })); + break; + case Tool.RemoveVoxel: + this.store.dispatch(removeVoxel({ position: pickInfo.pickedPoint })); + break; + } + } + + private calcNewVoxelPosition(pickInfo: PointerPickInfo): Coord { + return add(pickInfo.pickedPoint, pickInfo.normal); } } diff --git a/libs/ui/src/lib/scene-viewer/index.ts b/libs/ui/src/lib/scene-viewer/index.ts index 98820898..1fe437f1 100644 --- a/libs/ui/src/lib/scene-viewer/index.ts +++ b/libs/ui/src/lib/scene-viewer/index.ts @@ -1,2 +1,4 @@ export * from './scene-viewer.module'; export * from './scene-viewer.module.testing'; +export { PointerButton } from './pointer-button'; +export { PointerPickInfo } from './scene-viewer.service'; diff --git a/apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts b/libs/ui/src/lib/scene-viewer/pointer-button.ts similarity index 100% rename from apps/frontend/src/app/scene-viewer-container/pointer-button.model.ts rename to libs/ui/src/lib/scene-viewer/pointer-button.ts diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts index 6bdacd51..0abb3cdd 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts @@ -22,7 +22,6 @@ export class SceneViewerComponent implements OnInit { @ViewChild('canvas', { static: true }) canvas: ElementRef; @Output() pointerPick = this.sceneViewerService.pointerPick$; - @Output() meshPick = this.sceneViewerService.meshPick$; constructor(private sceneViewerService: SceneViewerService) {} diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 894e48c4..9872137c 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -7,14 +7,14 @@ import { Engine } from '@babylonjs/core/Engines/engine'; import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight'; import '@babylonjs/core/Materials/standardMaterial'; import { Vector3 } from '@babylonjs/core/Maths/math.vector'; -import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh'; import { Mesh } from '@babylonjs/core/Meshes/mesh'; import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData'; import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder'; import '@babylonjs/core/Physics/physicsHelper'; // Needed for `onPointerPick` import { Scene } from '@babylonjs/core/scene'; -import { Grid, gridToMesh } from '@talus/vdb'; +import { Coord, Grid, gridToMesh } from '@talus/vdb'; import { Subject } from 'rxjs'; +import { PointerButton } from './pointer-button'; @Injectable() export class EngineFactory { @@ -50,8 +50,7 @@ export class CameraFactory { export class SceneViewerService { scene: Scene; - pointerPick$ = new Subject(); - meshPick$ = new Subject(); + pointerPick$ = new Subject(); private engine: Engine; // @ts-ignore: noUnusedLocals @@ -111,8 +110,13 @@ export class SceneViewerService { private registerPointerPick(): void { this.scene.onPointerPick = (event: PointerEvent, pickInfo: PickingInfo): void => { - this.pointerPick$.next(event); - this.meshPick$.next(pickInfo.pickedMesh); + const info: PointerPickInfo = { + pickedPoint: vector3ToCoord(pickInfo.pickedPoint), + pointerButton: event.button, + normal: vector3ToCoord(pickInfo.getNormal()), + }; + + this.pointerPick$.next(info); }; } @@ -140,3 +144,13 @@ export class SceneViewerService { gridMesh.convertToFlatShadedMesh(); } } + +function vector3ToCoord(vector: Vector3): Coord { + return [vector.x, vector.y, vector.z]; +} + +export interface PointerPickInfo { + pickedPoint: Coord; + pointerButton: PointerButton; + normal: Coord; +} diff --git a/libs/vdb/src/lib/math/coord.ts b/libs/vdb/src/lib/math/coord.ts index cb979fa4..0001351f 100644 --- a/libs/vdb/src/lib/math/coord.ts +++ b/libs/vdb/src/lib/math/coord.ts @@ -13,6 +13,10 @@ export const Z = 2; export type Coord = [number, number, number]; +export function add(c1: Coord, c2: Coord): Coord { + return [c1[0] + c2[0], c1[1] + c2[1], c1[2] + c2[2]]; +} + export function createMaxCoord(): Coord { return [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]; } From f9c122bc515988d2e0579b27d32d27daefa69803 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 11 Dec 2019 13:08:59 +0100 Subject: [PATCH 07/67] build(packaging): simplify `prettier:check` command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 46a607f2..055fef75 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "lint:styles": "stylelint \"{apps,libs}/**/*.{css,scss}\"", "ng": "ng", "nx": "nx", - "prettier:check": "yarn prettier --check --config ./.prettierrc --ignore-path ./.prettierignore '{*,\\.circleci/**/*,apps/**/*,libs/**/*}.{ts,scss,json,html,yml}'", + "prettier:check": "yarn prettier --check --config ./.prettierrc --ignore-path ./.prettierignore '{*,\\.circleci,apps,libs}/**/*.{ts,scss,json,html,yml}'", "start": "ng serve", "test": "ng test", "test:code-coverage": "ng test --code-coverage", From 72c89e0ff49465be4ce4bb31e6bd67c9ba76d9c3 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 11 Dec 2019 13:19:23 +0100 Subject: [PATCH 08/67] doc(frontend): add readme with ngrx resources --- apps/frontend/README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/frontend/README.md diff --git a/apps/frontend/README.md b/apps/frontend/README.md new file mode 100644 index 00000000..442e0a36 --- /dev/null +++ b/apps/frontend/README.md @@ -0,0 +1,6 @@ +# Frontend + +## NgRx + +- [ngrx.io](https://ngrx.io/) +- [example-app](https://github.com/ngrx/platform/tree/master/projects/example-app) From d6eafd56e14fd96f1a32188787609da225a33dbc Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 10:16:10 +0100 Subject: [PATCH 09/67] feat(frontend): support adding voxel --- apps/frontend/src/app/app.reducer.ts | 23 ++++++-- .../scene-viewer-container/grid.service.ts | 26 ++++++++++ .../scene-viewer-container.actions.ts | 4 ++ .../scene-viewer-container.component.ts | 17 +++--- .../scene-viewer-container.effects.ts | 51 ++++++++++++++++++ .../scene-viewer-container.module.ts | 10 +++- .../scene-viewer-container.reducer.ts | 24 +++++++++ .../app/tools-panel/tools-panel.reducer.ts | 2 +- libs/ui/src/lib/scene-viewer/index.ts | 3 +- .../scene-viewer/scene-viewer.component.ts | 1 - .../lib/scene-viewer/scene-viewer.module.ts | 4 +- .../lib/scene-viewer/scene-viewer.service.ts | 52 ++++++++----------- libs/vdb/src/lib/tools/grid-to-mesh.ts | 16 +++--- package.json | 1 + yarn.lock | 5 ++ 15 files changed, 184 insertions(+), 55 deletions(-) create mode 100644 apps/frontend/src/app/scene-viewer-container/grid.service.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts diff --git a/apps/frontend/src/app/app.reducer.ts b/apps/frontend/src/app/app.reducer.ts index eae008a3..82ec8af7 100644 --- a/apps/frontend/src/app/app.reducer.ts +++ b/apps/frontend/src/app/app.reducer.ts @@ -8,11 +8,12 @@ import { MetaReducer, } from '@ngrx/store'; import { environment } from '../environments/environment'; - +import * as fromSceneViewerContainer from './scene-viewer-container/scene-viewer-container.reducer'; import * as fromToolsPanel from './tools-panel/tools-panel.reducer'; export interface State { - [fromToolsPanel.toolsPanelFeatureKey]: fromToolsPanel.State; + [fromToolsPanel.featureKey]: fromToolsPanel.State; + [fromSceneViewerContainer.featureKey]: fromSceneViewerContainer.State; } /** @@ -26,7 +27,8 @@ export const ROOT_REDUCERS = new InjectionToken> 'Root reducers token', { factory: () => ({ - [fromToolsPanel.toolsPanelFeatureKey]: fromToolsPanel.reducer, + [fromToolsPanel.featureKey]: fromToolsPanel.reducer, + [fromSceneViewerContainer.featureKey]: fromSceneViewerContainer.reducer, }), }, ); @@ -52,11 +54,24 @@ export function logger(reducer: ActionReducer): ActionReducer { */ export const metaReducers: MetaReducer[] = !environment.production ? [logger] : []; +/** + * SceneViewerContainer reducers + */ +export const selectSceneViewerContainerState = createFeatureSelector< + State, + fromSceneViewerContainer.State +>(fromSceneViewerContainer.featureKey); + +export const selectVoxelCount = createSelector( + selectSceneViewerContainerState, + fromSceneViewerContainer.selectVoxelCount, +); + /** * ToolsPanel reducers */ export const selectToolsPanelState = createFeatureSelector( - fromToolsPanel.toolsPanelFeatureKey, + fromToolsPanel.featureKey, ); export const selectSelectedToolId = createSelector( diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts new file mode 100644 index 00000000..1b6fe40b --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { Coord, Grid, gridToMesh, MeshData } from '@talus/vdb'; + +/** + * Keeps the mutable state of the single grid. This state is not part of the store, due to + * the possible big size of the grid. Creating a new copy for the next state is impracticable. + * + * Supports editing the grid. + */ +@Injectable() +export class GridService { + grid = new Grid(0); + accessor = this.grid.getAccessor(); + + addVoxel(xyz: Coord, value: number): void { + this.accessor.setValue(xyz, value); + } + + removeVoxel(xyz: Coord): void { + // this.accessor.setValueOff(xyz, this.grid.background); + } + + computeMesh(): MeshData { + return gridToMesh(this.grid); + } +} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts index 350c0e51..d8f32abc 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -7,8 +7,12 @@ export const addVoxel = createAction( `${actionTypePrefix} Add voxel`, props<{ position: Coord; value: number }>(), ); +export const addVoxelFailed = createAction(`${actionTypePrefix} Add voxel failed`); +export const voxelAdded = createAction(`${actionTypePrefix} Voxel added`); export const removeVoxel = createAction( `${actionTypePrefix} Remove voxel`, props<{ position: Coord }>(), ); +export const removeVoxelFailed = createAction(`${actionTypePrefix} Remove voxel failed`); +export const voxelRemoved = createAction(`${actionTypePrefix} Voxel removed`); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index 0245d4e5..c9911d9c 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -1,12 +1,13 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; // import '@babylonjs/core/Rendering/edgesRenderer'; // import '@babylonjs/core/Rendering/outlineRenderer'; import { select, Store } from '@ngrx/store'; -import { PointerButton, PointerPickInfo } from '@talus/ui'; +import { PointerButton, PointerPickInfo, SceneViewerComponent } from '@talus/ui'; import { add, Coord } from '@talus/vdb'; import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; import { Tool } from '../tools-panel/tool.model'; +import { GridService } from './grid.service'; import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; @Component({ @@ -20,11 +21,13 @@ import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerContainerComponent { - private selectedToolId$: Observable; + @ViewChild(SceneViewerComponent, { static: false }) + private sceneViewerComponent: SceneViewerComponent; - constructor(private store: Store) { - this.selectedToolId$ = store.pipe(select(fromApp.selectSelectedToolId)); - } + selectedToolId$: Observable = this.store.pipe(select(fromApp.selectSelectedToolId)); + voxelCount$: Observable = this.store.pipe(select(fromApp.selectVoxelCount)); + + constructor(private gridService: GridService, private store: Store) {} onPointerPick(event: PointerPickInfo, selectedToolId: Tool): void { this.dispatchPickAction(event, selectedToolId); @@ -42,7 +45,7 @@ export class SceneViewerContainerComponent { switch (selectedToolId) { case Tool.AddVoxel: - this.store.dispatch(addVoxel({ position: this.calcNewVoxelPosition(pickInfo), value: 42 })); + this.store.dispatch(addVoxel({ position: pickInfo.pickedPoint, value: 42 })); break; case Tool.RemoveVoxel: this.store.dispatch(removeVoxel({ position: pickInfo.pickedPoint })); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts new file mode 100644 index 00000000..20571c6c --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { SceneViewerService } from '@talus/ui'; +import { of } from 'rxjs'; +import { catchError, map, tap } from 'rxjs/operators'; +import { GridService } from './grid.service'; +import { + addVoxel, + addVoxelFailed, + removeVoxel, + removeVoxelFailed, + voxelAdded, + voxelRemoved, +} from './scene-viewer-container.actions'; + +@Injectable() +export class SceneViewerContainerEffects { + constructor( + private actions$: Actions, + private gridService: GridService, + private sceneViewerService: SceneViewerService, + ) {} + + addVoxel$ = createEffect(() => + this.actions$.pipe( + ofType(addVoxel), + tap({ + next: ({ position, value }) => { + this.gridService.addVoxel(position, value); + this.sceneViewerService.updateGridMesh(this.gridService.computeMesh()); + }, + }), + map(() => voxelAdded()), + catchError(() => of(addVoxelFailed())), + ), + ); + + removeVoxel$ = createEffect(() => + this.actions$.pipe( + ofType(removeVoxel), + tap({ + next: ({ position }) => { + this.gridService.removeVoxel(position); + this.sceneViewerService.updateGridMesh(this.gridService.computeMesh()); + }, + }), + map(() => voxelRemoved()), + catchError(() => of(removeVoxelFailed())), + ), + ); +} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts index 6b7bf096..ac65b3af 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts @@ -1,11 +1,19 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { EffectsModule } from '@ngrx/effects'; import { SceneViewerModule } from '@talus/ui'; +import { GridService } from './grid.service'; import { SceneViewerContainerComponent } from './scene-viewer-container.component'; +import { SceneViewerContainerEffects } from './scene-viewer-container.effects'; @NgModule({ declarations: [SceneViewerContainerComponent], - imports: [CommonModule, SceneViewerModule], + imports: [ + CommonModule, + EffectsModule.forFeature([SceneViewerContainerEffects]), + SceneViewerModule, + ], exports: [SceneViewerContainerComponent], + providers: [GridService], }) export class SceneViewerContainerModule {} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts new file mode 100644 index 00000000..f89ac931 --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts @@ -0,0 +1,24 @@ +import { createReducer, on } from '@ngrx/store'; +import { voxelAdded } from './scene-viewer-container.actions'; + +export const featureKey = 'sceneViewerContainer'; + +export interface State { + voxelCount: number; +} + +export const initialState: State = { + voxelCount: 0, +}; + +export const reducer = createReducer( + initialState, + on(voxelAdded, state => { + return { + ...state, + voxelCount: state.voxelCount + 1, + }; + }), +); + +export const selectVoxelCount = (state: State) => state.voxelCount; diff --git a/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts b/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts index 134e1293..732957f6 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.reducer.ts @@ -2,7 +2,7 @@ import { createReducer, on } from '@ngrx/store'; import { Tool } from './tool.model'; import { selectTool } from './tools-panel.actions'; -export const toolsPanelFeatureKey = 'toolsPanel'; +export const featureKey = 'toolsPanel'; export interface State { selectedToolId: Tool; diff --git a/libs/ui/src/lib/scene-viewer/index.ts b/libs/ui/src/lib/scene-viewer/index.ts index 1fe437f1..14b12407 100644 --- a/libs/ui/src/lib/scene-viewer/index.ts +++ b/libs/ui/src/lib/scene-viewer/index.ts @@ -1,4 +1,5 @@ +export * from './scene-viewer.component'; export * from './scene-viewer.module'; export * from './scene-viewer.module.testing'; export { PointerButton } from './pointer-button'; -export { PointerPickInfo } from './scene-viewer.service'; +export { PointerPickInfo, SceneViewerService } from './scene-viewer.service'; diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts index 0abb3cdd..6c5538ae 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts @@ -15,7 +15,6 @@ import { SceneViewerService } from './scene-viewer.service'; `, styleUrls: ['./scene-viewer.component.scss'], - providers: [SceneViewerService], changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerComponent implements OnInit { diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts index 6fb8e213..c569b163 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts @@ -1,12 +1,12 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { SceneViewerComponent } from './scene-viewer.component'; -import { CameraFactory, EngineFactory } from './scene-viewer.service'; +import { CameraFactory, EngineFactory, SceneViewerService } from './scene-viewer.service'; @NgModule({ declarations: [SceneViewerComponent], imports: [CommonModule], exports: [SceneViewerComponent], - providers: [CameraFactory, EngineFactory], + providers: [CameraFactory, EngineFactory, SceneViewerService], }) export class SceneViewerModule {} diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 9872137c..4de11939 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -12,7 +12,7 @@ import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData'; import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder'; import '@babylonjs/core/Physics/physicsHelper'; // Needed for `onPointerPick` import { Scene } from '@babylonjs/core/scene'; -import { Coord, Grid, gridToMesh } from '@talus/vdb'; +import { Coord, MeshData } from '@talus/vdb'; import { Subject } from 'rxjs'; import { PointerButton } from './pointer-button'; @@ -46,9 +46,14 @@ export class CameraFactory { } } +/** + * This service allows to set a new mesh for `SceneViewerComponent` to render. This service is + * provided on module level. Therefore, only one `SceneViewerComponent` at the time is supported. + */ @Injectable() export class SceneViewerService { scene: Scene; + gridMesh: Mesh; pointerPick$ = new Subject(); @@ -60,14 +65,17 @@ export class SceneViewerService { initialize(canvas: HTMLCanvasElement): void { this.engine = this.engineFactory.create(canvas); + this.scene = new Scene(this.engine); - this.createScene(); this.createCamera(); this.createLight(); this.registerPointerPick(); - this.addGrid(); + const box = MeshBuilder.CreateBox('box', {}, this.scene); + box.position.x = 0.5; + box.position.y = 0.5; + box.position.z = 0.5; } startRendering(): void { @@ -78,10 +86,18 @@ export class SceneViewerService { this.engine.resize(); } - private createScene(): void { - this.scene = new Scene(this.engine); + updateGridMesh(mesh: MeshData): void { + this.scene.removeMesh(this.gridMesh); + + this.gridMesh = new Mesh('grid', this.scene); + const data = new VertexData(); + + data.colors = mesh.colors; + data.indices = mesh.indices; + data.positions = mesh.positions; - MeshBuilder.CreateBox('box', {}, this.scene); + data.applyToMesh(this.gridMesh); + this.gridMesh.convertToFlatShadedMesh(); } private createCamera(): void { @@ -119,30 +135,6 @@ export class SceneViewerService { this.pointerPick$.next(info); }; } - - private addGrid(): void { - const grid = new Grid(0); - const accessor = grid.getAccessor(); - - for (let x = -10; x < 10; x++) { - for (let z = -10; z < 10; z++) { - accessor.setValue([x, Math.sin(z / 4) * 10, z], 1); - } - } - - const mesh = gridToMesh(grid); - - const gridMesh = new Mesh('grid', this.scene); - const data = new VertexData(); - - data.colors = mesh.colors; - data.indices = mesh.indices; - data.normals = mesh.normals; - data.positions = mesh.positions; - - data.applyToMesh(gridMesh); - gridMesh.convertToFlatShadedMesh(); - } } function vector3ToCoord(vector: Vector3): Coord { diff --git a/libs/vdb/src/lib/tools/grid-to-mesh.ts b/libs/vdb/src/lib/tools/grid-to-mesh.ts index ee464603..84f6f377 100644 --- a/libs/vdb/src/lib/tools/grid-to-mesh.ts +++ b/libs/vdb/src/lib/tools/grid-to-mesh.ts @@ -19,7 +19,7 @@ import { Grid } from '../grid'; export interface MeshData { colors: number[]; indices: number[]; - normals: number[]; + // normals: number[]; positions: number[]; } @@ -28,7 +28,7 @@ export function gridToMesh(grid: Grid): MeshData { positions: [], indices: [], colors: [], - normals: [], + // normals: [], }; let vertexCount = 0; @@ -44,14 +44,14 @@ export function gridToMesh(grid: Grid): MeshData { mesh.indices.push(...[0, 1, 2, 2, 3, 0].map(i => i + vertexCount)); // Front mesh.indices.push(...[4, 5, 6, 6, 7, 4].map(i => i + vertexCount)); // Back - mesh.normals.push(-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0); // Left - mesh.normals.push(1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0); // Right + // mesh.normals.push(-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0); // Left + // mesh.normals.push(1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0); // Right - mesh.normals.push(0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0); // Bottom - mesh.normals.push(0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0); // Top + // mesh.normals.push(0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0); // Bottom + // mesh.normals.push(0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0); // Top - mesh.normals.push(0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1); // Front - mesh.normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1); // Back + // mesh.normals.push(0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1); // Front + // mesh.normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1); // Back mesh.positions.push(x, y, z); // 0 mesh.positions.push(x + 1, y, z); // 1 diff --git a/package.json b/package.json index 055fef75..e8580bc0 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@angular/router": "8.2.14", "@babylonjs/core": "4.1.0-beta.9", "@babylonjs/materials": "4.1.0-beta.9", + "@ngrx/effects": "8.5.2", "@ngrx/store": "8.5.2", "@nrwl/angular": "8.9.0", "core-js": "3.4.8", diff --git a/yarn.lock b/yarn.lock index d0046519..af6c6a03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1162,6 +1162,11 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@ngrx/effects@8.5.2": + version "8.5.2" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-8.5.2.tgz#c4f81947f4028a0d678ed2641101481cdbe11b59" + integrity sha512-i2rKLmFcfJmPPQRul1PuXXRuBX2q1g7tK6DbWreNabU/46fYlEwqiiW6lU53t3AgJ3yd6UpeLTR6CHTflkzL+w== + "@ngrx/store@8.5.2": version "8.5.2" resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-8.5.2.tgz#18e4a39f3e7ac2ec8307653837ec3c4153bde04f" From 2e68605d757d7aacc2d691ad36d40962f5cacb9a Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 11:42:54 +0100 Subject: [PATCH 10/67] refactor(frontend): don't inject `GridService` --- .../scene-viewer-container/scene-viewer-container.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index c9911d9c..8220529f 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -7,7 +7,6 @@ import { add, Coord } from '@talus/vdb'; import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; import { Tool } from '../tools-panel/tool.model'; -import { GridService } from './grid.service'; import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; @Component({ @@ -27,7 +26,7 @@ export class SceneViewerContainerComponent { selectedToolId$: Observable = this.store.pipe(select(fromApp.selectSelectedToolId)); voxelCount$: Observable = this.store.pipe(select(fromApp.selectVoxelCount)); - constructor(private gridService: GridService, private store: Store) {} + constructor(private store: Store) {} onPointerPick(event: PointerPickInfo, selectedToolId: Tool): void { this.dispatchPickAction(event, selectedToolId); From 157da40f7119520c79efde3ff8db5738e15b9fa9 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 13:04:40 +0100 Subject: [PATCH 11/67] feat(frontend): effects for when app goes on/offline --- apps/frontend/src/app/app.actions.ts | 6 ++++++ apps/frontend/src/app/app.effects.ts | 19 +++++++++++++++++++ apps/frontend/src/app/app.module.ts | 3 +++ 3 files changed, 28 insertions(+) create mode 100644 apps/frontend/src/app/app.actions.ts create mode 100644 apps/frontend/src/app/app.effects.ts diff --git a/apps/frontend/src/app/app.actions.ts b/apps/frontend/src/app/app.actions.ts new file mode 100644 index 00000000..ab592e7e --- /dev/null +++ b/apps/frontend/src/app/app.actions.ts @@ -0,0 +1,6 @@ +import { createAction } from '@ngrx/store'; + +const actionTypePrefix = '[App]'; + +export const wentOnline = createAction(`${actionTypePrefix} Went online`); +export const wentOffline = createAction(`${actionTypePrefix} Went offline`); diff --git a/apps/frontend/src/app/app.effects.ts b/apps/frontend/src/app/app.effects.ts new file mode 100644 index 00000000..bbb6e268 --- /dev/null +++ b/apps/frontend/src/app/app.effects.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect } from '@ngrx/effects'; +import { fromEvent, merge, of } from 'rxjs'; +import { map, mapTo } from 'rxjs/operators'; +import { wentOffline, wentOnline } from './app.actions'; + +@Injectable() +export class AppEffects { + constructor(private actions$: Actions) {} + + // @source: https://indepth.dev/start-using-ngrx-effects-for-this/#1externalsources + onlineStateChange$ = createEffect(() => { + return merge( + of(navigator.onLine), + fromEvent(window, 'online').pipe(mapTo(true)), + fromEvent(window, 'offline').pipe(mapTo(false)), + ).pipe(map(isOnline => (isOnline ? wentOnline() : wentOffline()))); + }); +} diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts index 2238a7d0..58db50bd 100644 --- a/apps/frontend/src/app/app.module.ts +++ b/apps/frontend/src/app/app.module.ts @@ -2,9 +2,11 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterModule } from '@angular/router'; +import { EffectsModule } from '@ngrx/effects'; import { StoreModule } from '@ngrx/store'; import { SidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; +import { AppEffects } from './app.effects'; import { metaReducers, ROOT_REDUCERS } from './app.reducer'; import { SceneViewerContainerModule } from './scene-viewer-container'; import { ToolsPanelModule } from './tools-panel/tools-panel.module'; @@ -14,6 +16,7 @@ import { ToolsPanelModule } from './tools-panel/tools-panel.module'; imports: [ BrowserModule, BrowserAnimationsModule, + EffectsModule.forRoot([AppEffects]), RouterModule.forRoot([], { initialNavigation: 'enabled' }), /** * StoreModule.forRoot is imported once in the root module, accepting a reducer From 4ad0a040d87177bc2db08f0b1069450cce6ff3d2 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 15:03:37 +0100 Subject: [PATCH 12/67] test(frontend): on/offline effects --- apps/frontend/src/app/app.effects.spec.ts | 29 +++++++++++++++++++++++ apps/frontend/src/app/app.effects.ts | 4 +--- package.json | 1 + yarn.lock | 2 +- 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 apps/frontend/src/app/app.effects.spec.ts diff --git a/apps/frontend/src/app/app.effects.spec.ts b/apps/frontend/src/app/app.effects.spec.ts new file mode 100644 index 00000000..c67d1211 --- /dev/null +++ b/apps/frontend/src/app/app.effects.spec.ts @@ -0,0 +1,29 @@ +import { hot } from 'jasmine-marbles'; +import { wentOffline, wentOnline } from './app.actions'; +import { AppEffects } from './app.effects'; + +describe('AppEffects', () => { + let effects: AppEffects; + + beforeEach(() => { + effects = new AppEffects(); + + Object.defineProperty(navigator, 'onLine', { value: false }); + }); + + it('should dispatch `wentOnline` action', () => { + const expected = hot('a', { + a: wentOnline(), + }); + + expect(effects.onlineStateChange$).toBeObservable(expected); + }); + + it('should dispatch `wentOffline` action', () => { + const expected = hot('a', { + a: wentOffline(), + }); + + expect(effects.onlineStateChange$).toBeObservable(expected); + }); +}); diff --git a/apps/frontend/src/app/app.effects.ts b/apps/frontend/src/app/app.effects.ts index bbb6e268..61488e36 100644 --- a/apps/frontend/src/app/app.effects.ts +++ b/apps/frontend/src/app/app.effects.ts @@ -1,13 +1,11 @@ import { Injectable } from '@angular/core'; -import { Actions, createEffect } from '@ngrx/effects'; +import { createEffect } from '@ngrx/effects'; import { fromEvent, merge, of } from 'rxjs'; import { map, mapTo } from 'rxjs/operators'; import { wentOffline, wentOnline } from './app.actions'; @Injectable() export class AppEffects { - constructor(private actions$: Actions) {} - // @source: https://indepth.dev/start-using-ngrx-effects-for-this/#1externalsources onlineStateChange$ = createEffect(() => { return merge( diff --git a/package.json b/package.json index e8580bc0..11ca24c4 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "cypress": "3.7.0", "dotenv": "8.2.0", "gh-pages": "2.1.1", + "jasmine-marbles": "0.6.0", "jest": "24.9.0", "jest-junit": "10.0.0", "jest-preset-angular": "7.1.1", diff --git a/yarn.lock b/yarn.lock index af6c6a03..689573ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5612,7 +5612,7 @@ istanbul-reports@^2.2.6: dependencies: handlebars "^4.1.2" -jasmine-marbles@~0.6.0: +jasmine-marbles@0.6.0, jasmine-marbles@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.6.0.tgz#f78dc1a3bc452976de10ee8b47c73d616532a954" integrity sha512-1uzgjEesEeCb+r+v46qn5x326TiGqk5SUZa+A3O+XnMCjG/pGcUOhL9Xsg5L7gLC6RFHyWGTkB5fei4rcvIOiQ== From f7419ebc311ec1a0429b3b7c11238392b4d5430b Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 15:05:29 +0100 Subject: [PATCH 13/67] test(vdb): remove `normals` from test --- libs/vdb/src/lib/tools/grid-to-mesh.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts b/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts index 96829fd7..ab6a602f 100644 --- a/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts +++ b/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts @@ -22,6 +22,5 @@ describe('gridToMesh()', () => { expect(meshData.positions.length).toEqual(voxels * corners * xyz); expect(meshData.colors.length).toEqual(voxels * corners * rgba); expect(meshData.indices.length).toEqual(voxels * triangles * xyz); - expect(meshData.normals.length).toEqual(voxels * triangles * 3 * xyz); }); }); From 99fed10c84100b0bf5cdd6388daa54d7df96c51b Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 16:14:09 +0100 Subject: [PATCH 14/67] feat(vdb): add `setValueOff` & `isValueOn` --- libs/vdb/src/lib/tree/internal-node.ts | 36 ++++++++++++++++ libs/vdb/src/lib/tree/leaf-node.ts | 29 +++++++++++++ libs/vdb/src/lib/tree/node.ts | 16 +++++++ libs/vdb/src/lib/tree/root-node.ts | 40 +++++++++++++++++- libs/vdb/src/lib/tree/value-accessor.spec.ts | 44 ++++++++++++++++++++ libs/vdb/src/lib/tree/value-accessor.ts | 32 ++++++++++++++ 6 files changed, 196 insertions(+), 1 deletion(-) diff --git a/libs/vdb/src/lib/tree/internal-node.ts b/libs/vdb/src/lib/tree/internal-node.ts index fd0118b8..306bce01 100644 --- a/libs/vdb/src/lib/tree/internal-node.ts +++ b/libs/vdb/src/lib/tree/internal-node.ts @@ -109,6 +109,9 @@ abstract class InternalNode implements HashableNode { const active = this.valueMask.isOn(i); // tile's active state if (!active || node.getValue() !== value) { + // If the voxel belongs to a tile that is either inactive or that + // has a constant value that is different from the one provided, + // a child subtree must be constructed. hasChild = true; this.setChildNode(i, this.createChildNode(xyz, node.getValue(), active)); } @@ -120,6 +123,29 @@ abstract class InternalNode implements HashableNode { } } + setValueOffAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void { + const i: Index = this.coordToOffset(xyz); + const node = this.nodes[i]; + let hasChild = this.childMask.isOn(i); + + if (!hasChild) { + const active = this.valueMask.isOn(i); // tile's active state + + if (active || node.getValue() !== value) { + // If the voxel belongs to a tile that is either active or that + // has a constant value that is different from the one provided, + // a child subtree must be constructed. + hasChild = true; + this.setChildNode(i, this.createChildNode(xyz, node.getValue(), active)); + } + } + + if (hasChild) { + accessor.insert(xyz, node.getChild()); + node.getChild().setValueOffAndCache(xyz, value, accessor); + } + } + isValueOn(xyz: Coord): boolean { const i: Index = this.coordToOffset(xyz); if (this.childMask.isOff(i)) { @@ -129,6 +155,16 @@ abstract class InternalNode implements HashableNode { return this.nodes[i].getChild().isValueOn(xyz); } + isValueOnAndCache(xyz: Coord, accessor: ValueAccessor3): boolean { + const i: Index = this.coordToOffset(xyz); + if (this.childMask.isOff(i)) { + return this.valueMask.isOn(i); + } + + accessor.insert(xyz, this.nodes[i].getChild()); + return this.nodes[i].getChild().isValueOnAndCache(xyz, accessor); + } + *beginVoxelOn(): IterableIterator> { for (const index of this.childMask.beginOn()) { const child = this.nodes[index].getChild(); diff --git a/libs/vdb/src/lib/tree/leaf-node.ts b/libs/vdb/src/lib/tree/leaf-node.ts index 70f8f459..4cada089 100644 --- a/libs/vdb/src/lib/tree/leaf-node.ts +++ b/libs/vdb/src/lib/tree/leaf-node.ts @@ -76,6 +76,9 @@ export class LeafNode implements HashableNode { // tslint:enable:no-bitwise } + /** + * Set the value of the voxel at the given coordinates and mark the voxel as active. + */ setValueOn(xyz: Coord, value: T): void { const offset = LeafNode.coordToOffset(xyz); @@ -83,6 +86,16 @@ export class LeafNode implements HashableNode { this.valueMask.setOn(offset); } + /** + * Set the value of the voxel at the given coordinates and mark the voxel as inactive. + */ + setValueOff(xyz: Coord, value: T): void { + const offset = LeafNode.coordToOffset(xyz); + + this.buffer.setValue(offset, value); + this.valueMask.setOff(offset); + } + /** * Return the value of the voxel at the given coordinates. */ @@ -114,6 +127,22 @@ export class LeafNode implements HashableNode { this.setValueOn(xyz, value); } + /** + * @brief Change the value of the voxel at the given coordinates and mark it as inactive. + * @note Used internally by ValueAccessor. + */ + setValueOffAndCache(xyz: Coord, value: T, _: ValueAccessor3): void { + this.setValueOff(xyz, value); + } + + /** + * @brief Return `true` if the voxel at the given coordinates is active. + * @note Used internally by ValueAccessor. + */ + isValueOnAndCache(xyz: Coord, _: ValueAccessor3): boolean { + return this.isValueOn(xyz); + } + /** * Return the global coordinates for a linear table offset. */ diff --git a/libs/vdb/src/lib/tree/node.ts b/libs/vdb/src/lib/tree/node.ts index 9f3ef281..e4c34174 100644 --- a/libs/vdb/src/lib/tree/node.ts +++ b/libs/vdb/src/lib/tree/node.ts @@ -40,6 +40,22 @@ export interface HashableNode extends Node { * @note Used internally by ValueAccessor. */ setValueAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void; + + /** + * Change the value of the voxel at the given coordinates and mark it as inactive. + * If necessary, update the accessor with pointers to the nodes along the path + * from the root node to the node containing the voxel. + * @note Used internally by ValueAccessor. + */ + setValueOffAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void; + + /** + * Return `true` if the voxel at the given coordinates is active and, if necessary, + * update the accessor with pointers to the nodes along the path from the root node + * to the node containing the voxel. + * @note Used internally by ValueAccessor. + */ + isValueOnAndCache(xyz: Coord, accessor: ValueAccessor3): boolean; } export interface IterableNode { diff --git a/libs/vdb/src/lib/tree/root-node.ts b/libs/vdb/src/lib/tree/root-node.ts index 36f29370..20d3dc9e 100644 --- a/libs/vdb/src/lib/tree/root-node.ts +++ b/libs/vdb/src/lib/tree/root-node.ts @@ -77,8 +77,8 @@ export class RootNode implements HashableNode { } setValueAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void { - const struct = this.findCoord(xyz); let child: HashableNode; + const struct = this.findCoord(xyz); if (!struct) { child = new InternalNode2(xyz, this._background); @@ -96,6 +96,28 @@ export class RootNode implements HashableNode { } } + setValueOffAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void { + let child: HashableNode; + const struct = this.findCoord(xyz); + + if (!struct) { + if (this._background !== value) { + child = new InternalNode2(xyz, this._background); + this.table.set(RootNode.coordToKey(xyz), new NodeStruct(child)); + } + } else if (struct.isChild()) { + child = struct.getChild(); + } else if (struct.isTileOn() || struct.getTile().value !== value) { + child = new InternalNode2(xyz, struct.getTile().value, struct.isTileOn()); + struct.setChild(child); + } + + if (child) { + accessor.insert(xyz, child); + child.setValueOffAndCache(xyz, value, accessor); + } + } + isValueOn(xyz: Coord): boolean { const struct = this.findCoord(xyz); @@ -106,6 +128,22 @@ export class RootNode implements HashableNode { return struct.isTileOn() ? true : struct.getChild().isValueOn(xyz); } + isValueOnAndCache(xyz: Coord, accessor: ValueAccessor3): boolean { + const struct = this.findCoord(xyz); + + if (!struct || struct.isTileOff()) { + return false; + } + + if (struct.isTileOn()) { + return true; + } + + accessor.insert(xyz, struct.getChild()); + + return struct.getChild().isValueOnAndCache(xyz, accessor); + } + onVoxelCount(): number { let sum = 0; for (const nodeStruct of this.table.values()) { diff --git a/libs/vdb/src/lib/tree/value-accessor.spec.ts b/libs/vdb/src/lib/tree/value-accessor.spec.ts index b5f6f29e..425daade 100644 --- a/libs/vdb/src/lib/tree/value-accessor.spec.ts +++ b/libs/vdb/src/lib/tree/value-accessor.spec.ts @@ -12,6 +12,7 @@ describe('ValueAccessor', () => { const value = accessor.getValue([0, 0, 0]); expect(value).toEqual(1496); + expect(accessor.isCached([0, 0, 0])).toBeTruthy(); expect(accessor.isCached([0, 0, 8])).toBeTruthy(); expect(accessor.isCached([0, 8, 0])).toBeTruthy(); @@ -30,12 +31,55 @@ describe('ValueAccessor', () => { const value = accessor.getValue([0, 0, 0]); expect(value).toEqual(1496); + + expect(accessor.isCached([0, 0, 0])).toBeTruthy(); + expect(accessor.isCached([0, 0, 8])).toBeTruthy(); + expect(accessor.isCached([0, 8, 0])).toBeTruthy(); + expect(accessor.isCached([8, 0, 0])).toBeTruthy(); + expect(accessor.isCached([0, 0, InternalNode2.DIM - 1])).toBeTruthy(); + expect(accessor.isCached([0, 0, InternalNode2.DIM])).toBeFalsy(); + + expect(accessor.isValueOn([0, 0, 0])).toBeTruthy(); + }); + }); + + describe('setValueOff()', () => { + it('should cache coordinate', () => { + const tree = new Tree(0); + const accessor = new ValueAccessor3(tree); + + accessor.setValueOff([0, 0, 0], 1496); + const value = accessor.getValue([0, 0, 0]); + + expect(value).toEqual(1496); + expect(accessor.isCached([0, 0, 0])).toBeTruthy(); expect(accessor.isCached([0, 0, 8])).toBeTruthy(); expect(accessor.isCached([0, 8, 0])).toBeTruthy(); expect(accessor.isCached([8, 0, 0])).toBeTruthy(); expect(accessor.isCached([0, 0, InternalNode2.DIM - 1])).toBeTruthy(); expect(accessor.isCached([0, 0, InternalNode2.DIM])).toBeFalsy(); + + expect(accessor.isValueOn([0, 0, 0])).toBeFalsy(); + }); + }); + + describe('isValueOn()', () => { + it('should set value and (de)activate voxel', () => { + const tree = new Tree(0); + const accessor = new ValueAccessor3(tree); + + accessor.setValueOn([0, 0, 1], 4321); + accessor.setValueOff([42, 638, 2], 1234); + + expect(accessor.getValue([0, 0, 1])).toEqual(4321); + expect(accessor.getValue([42, 638, 2])).toEqual(1234); + + expect(accessor.isValueOn([0, 0, 1])).toBeTruthy(); + expect(accessor.isValueOn([42, 638, 2])).toBeFalsy(); + + accessor.setValueOff([0, 0, 1], 1); + expect(accessor.isValueOn([0, 0, 1])).toBeFalsy(); }); }); }); diff --git a/libs/vdb/src/lib/tree/value-accessor.ts b/libs/vdb/src/lib/tree/value-accessor.ts index feac29c2..9ba01796 100644 --- a/libs/vdb/src/lib/tree/value-accessor.ts +++ b/libs/vdb/src/lib/tree/value-accessor.ts @@ -75,6 +75,38 @@ export class ValueAccessor3 { this.tree.root.setValueAndCache(xyz, value, this); } } + setValueOn(xyz: Coord, value: T): void { + this.setValue(xyz, value); + } + + /** + * Set the value of the voxel at the given coordinates and mark the voxel as inactive. + */ + setValueOff(xyz: Coord, value: T): void { + if (this.isHashed0(xyz)) { + this.leafNode.setValueOffAndCache(xyz, value, this); + } else if (this.isHashed1(xyz)) { + this.internalNode1.setValueOffAndCache(xyz, value, this); + } else if (this.isHashed2(xyz)) { + this.internalNode2.setValueOffAndCache(xyz, value, this); + } else { + this.tree.root.setValueOffAndCache(xyz, value, this); + } + } + + /** + * Return the active state of the voxel at the given coordinates. + */ + isValueOn(xyz: Coord): boolean { + if (this.isHashed0(xyz)) { + return this.leafNode.isValueOnAndCache(xyz, this); + } else if (this.isHashed1(xyz)) { + return this.internalNode1.isValueOnAndCache(xyz, this); + } else if (this.isHashed2(xyz)) { + return this.internalNode2.isValueOnAndCache(xyz, this); + } + return this.tree.root.isValueOnAndCache(xyz, this); + } // tslint:disable:no-bitwise insert(xyz: Coord, node: HashableNode): void { From 29161bc0b35eaf045dfb4a10a7f02bee1a6a673f Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 16:24:10 +0100 Subject: [PATCH 15/67] test(frontend): set expected position to pass --- .../scene-viewer-container.component.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 3f3da356..43243d9e 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -24,6 +24,7 @@ describe('SceneViewerContainerComponent', () => { let component: SceneViewerContainerComponent; let stubComponent: SceneViewerStubComponent; let fixture: ComponentFixture; + let mockStore: MockStore; let mockSelectedToolIdSelector: MemoizedSelector; @@ -68,7 +69,7 @@ describe('SceneViewerContainerComponent', () => { }); it('should dispatch `addVoxel` action', () => { - const action = addVoxel({ position: [1, 1, 2], value: 42 }); + const action = addVoxel({ position: [1, 1, 1], value: 42 }); stubComponent.pointerPick.next({ pickedPoint: [1, 1, 1], From c01594402d0c4053aa33854a179b8e7b226072a4 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 16:35:48 +0100 Subject: [PATCH 16/67] fix(frontend): make public for use in template --- apps/frontend/src/app/tools-panel/tools-panel.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/app/tools-panel/tools-panel.component.ts b/apps/frontend/src/app/tools-panel/tools-panel.component.ts index 3c84f224..5def4721 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.component.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.component.ts @@ -18,7 +18,7 @@ import { selectTool } from './tools-panel.actions'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ToolsPanelComponent { - private selectedToolId$: Observable; + selectedToolId$: Observable; tools: UiToolbarToolConfig[] = [ { From 31ea92067736a00338f4e0da5a63bd19e50beffa Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 16:47:23 +0100 Subject: [PATCH 17/67] build(dep): `@types/node` & `core-js` --- package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 11ca24c4..54ee6e39 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@ngrx/effects": "8.5.2", "@ngrx/store": "8.5.2", "@nrwl/angular": "8.9.0", - "core-js": "3.4.8", + "core-js": "3.5.0", "hammerjs": "2.0.8", "mnemonist": "0.31.3", "rxjs": "6.5.3", @@ -67,7 +67,7 @@ "@nrwl/workspace": "8.9.0", "@types/benchmark": "1.0.31", "@types/jest": "24.0.23", - "@types/node": "12.12.16", + "@types/node": "12.12.17", "babylonjs": "4.1.0-beta.9", "benchmark": "2.1.4", "codelyzer": "5.2.0", diff --git a/yarn.lock b/yarn.lock index 689573ed..28999fc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1427,10 +1427,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== -"@types/node@12.12.16": - version "12.12.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.16.tgz#3ebcbd7bf978fa4c5120fee8be57083271a8b3ac" - integrity sha512-vRuMyoOr5yfNf8QWxXegOjeyjpWJxFePzHzmBOIzDIzo+rSqF94RW0PkS6y4T2+VjAWLXHWrfbIJY3E3aS7lUw== +"@types/node@12.12.17": + version "12.12.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b" + integrity sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA== "@types/parse-json@^4.0.0": version "4.0.0" @@ -3170,10 +3170,10 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@3.4.8: - version "3.4.8" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.8.tgz#e0fc0c61f2ef90cbc10c531dbffaa46dfb7152dd" - integrity sha512-b+BBmCZmVgho8KnBUOXpvlqEMguko+0P+kXCwD4vIprsXC6ht1qgPxtb1OK6XgSlrySF71wkwBQ0Hv695bk9gQ== +core-js@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.5.0.tgz#66df8e49be4bd775e6f952a9d083b756ad41c1ed" + integrity sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw== core-js@^2.4.0: version "2.6.9" From 11fa2eb4dfdcff3da5d393a1055dc4eba96c8d78 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 16:51:17 +0100 Subject: [PATCH 18/67] feat(frontend): enable `removeVoxel` --- apps/frontend/src/app/scene-viewer-container/grid.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index 1b6fe40b..bf5474c9 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -17,7 +17,7 @@ export class GridService { } removeVoxel(xyz: Coord): void { - // this.accessor.setValueOff(xyz, this.grid.background); + this.accessor.setValueOff(xyz, this.grid.background); } computeMesh(): MeshData { From 5a8df987cf29f756007e79ce87fae7db8732e3ad Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 17:17:59 +0100 Subject: [PATCH 19/67] build(dep): `@babylonjs/*` --- package.json | 8 ++--- yarn.lock | 90 ++++++++++++++++++++++++++-------------------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index 54ee6e39..9549c7db 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "@angular/platform-browser": "8.2.14", "@angular/platform-browser-dynamic": "8.2.14", "@angular/router": "8.2.14", - "@babylonjs/core": "4.1.0-beta.9", - "@babylonjs/materials": "4.1.0-beta.9", + "@babylonjs/core": "4.1.0-beta.12", + "@babylonjs/materials": "4.1.0-beta.12", "@ngrx/effects": "8.5.2", "@ngrx/store": "8.5.2", "@nrwl/angular": "8.9.0", @@ -60,7 +60,7 @@ "@angular/cli": "8.3.20", "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", - "@babylonjs/inspector": "4.1.0-beta.9", + "@babylonjs/inspector": "4.1.0-beta.12", "@nrwl/cypress": "8.9.0", "@nrwl/jest": "8.9.0", "@nrwl/node": "8.9.0", @@ -68,7 +68,7 @@ "@types/benchmark": "1.0.31", "@types/jest": "24.0.23", "@types/node": "12.12.17", - "babylonjs": "4.1.0-beta.9", + "babylonjs": "4.1.0-beta.12", "benchmark": "2.1.4", "codelyzer": "5.2.0", "cypress": "3.7.0", diff --git a/yarn.lock b/yarn.lock index 28999fc9..fcfbc79b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -914,58 +914,58 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babylonjs/core@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.9.tgz#e77c3ddde0354b305aab0f234a7c4901914c8ae4" - integrity sha512-8jluf2f0ip+abcWNZn01eONB4joFR2lFWbpIk6L4x9lu/H5eENUT4WKqJ+1zFSKz2mWi0VJBu2snojC+I6JRKw== +"@babylonjs/core@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.12.tgz#9aaaa51fa4fc72defb9e444d8376294f3bccbb0b" + integrity sha512-o5IUXJJWwZpON4YRytvYJkdhuKVf5Kf8bieotp4TVqo+ECB+mUGvxkDFoa/Mc1A0QLT7YcDSuibYQbu6asRrTQ== dependencies: tslib "^1.10.0" -"@babylonjs/gui@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.9.tgz#7668b1b6a04e952e40a9d2b0ecab8742cf7e7e1e" - integrity sha512-bm3Bq+Ldy+n1jIkBCg/4cCxGV0zJe6uGQ2wLxtMqL2xVgBDO6rIdLCZBEFMeAjs/18d0ceNeONk8kLhVEtiLSQ== +"@babylonjs/gui@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.12.tgz#b467209fde28479e340dd0db107736b0334ae6a3" + integrity sha512-7WjS0liqvtSnJKqCR3ft2cwyOlqFiAUDQwzsSax4f1Iq9ql4M5J5+LC0FLXgkAGiltut8JjioSdEG39kD3T0TA== dependencies: - "@babylonjs/core" "4.1.0-beta.9" + "@babylonjs/core" "4.1.0-beta.12" tslib "^1.10.0" -"@babylonjs/inspector@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.9.tgz#dfd0ec78180dabe569bb16702f2dcef572557f40" - integrity sha512-6tT+rc3UMdKiNugYNAJxBP5Zza+2ABLgscCc5VG8rDGap0i6x/6aPoYEvZ0iGNQCrjvS66kd5/vVtCyoc+ISuQ== - dependencies: - "@babylonjs/core" "4.1.0-beta.9" - "@babylonjs/gui" "4.1.0-beta.9" - "@babylonjs/loaders" "4.1.0-beta.9" - "@babylonjs/materials" "4.1.0-beta.9" - "@babylonjs/serializers" "4.1.0-beta.9" - babylonjs-gltf2interface "4.1.0-beta.9" +"@babylonjs/inspector@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.12.tgz#c2e489b2a6a29d65523eec93a44346b1e65c97ec" + integrity sha512-Wga2Q5Gu5CBiR3zNMV30hCeTlDt5DxOGogOmMlkU9IfXg84VcpgjjHa4a1NV/nDaJtOP+sANKIvxVyAgtMhhhQ== + dependencies: + "@babylonjs/core" "4.1.0-beta.12" + "@babylonjs/gui" "4.1.0-beta.12" + "@babylonjs/loaders" "4.1.0-beta.12" + "@babylonjs/materials" "4.1.0-beta.12" + "@babylonjs/serializers" "4.1.0-beta.12" + babylonjs-gltf2interface "4.1.0-beta.12" tslib "^1.10.0" -"@babylonjs/loaders@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.9.tgz#33582c15ec144403db2cf1e614ac4c26d11e185f" - integrity sha512-0QPDIzaAxe3UOK/vzz4EPrH90CGO8cYJS5ev74sySwsodTkEDCgcyBuGsJYNQic1yje2SWrcBUWfaVCm/8QcYA== +"@babylonjs/loaders@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.12.tgz#a0225a705507705ca9d4730eede87c95aa4b84c7" + integrity sha512-FIZxjltGLMP3DSCtos365HjPpL7zOfzkERe+X5/yy9zkMKPrzZGcKv90MZyEx+9lrjMTV3sueDMNTnp6d9pc/g== dependencies: - "@babylonjs/core" "4.1.0-beta.9" - babylonjs-gltf2interface "4.1.0-beta.9" + "@babylonjs/core" "4.1.0-beta.12" + babylonjs-gltf2interface "4.1.0-beta.12" tslib "^1.10.0" -"@babylonjs/materials@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.9.tgz#4ca9601bdb61338f3b0dc874a5ccaff9a9b3a37c" - integrity sha512-NBYMHtgPSm2BZn9FcUgeb4eVJXForv4sR2gt6UKBdAUeA8AXoJc5fATQEwybEFwGMDafB1XFfP7bIxCBJy/jMg== +"@babylonjs/materials@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.12.tgz#71dfe537b54c243e8c7db0a46683986c6d284008" + integrity sha512-lwJ6SZySiQiT+dijkg3yddgU71sGzmiO2Zm8JzSsRJkuA2P6K8s1sZUDVAhI5h6Im8i7LiSFWLPQQjZsDaOAkA== dependencies: - "@babylonjs/core" "4.1.0-beta.9" + "@babylonjs/core" "4.1.0-beta.12" tslib "^1.10.0" -"@babylonjs/serializers@4.1.0-beta.9": - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.9.tgz#f92db8df538e0e823bf68a69c4a4f684a889b6bf" - integrity sha512-ai92CPa48Q1aUxfVN/bLIoTfWssPeEFojs2eTwox8CnipcI4Njl7qGyT9FQRoe1AvmGpn6GR4baXawj4WPQnpQ== +"@babylonjs/serializers@4.1.0-beta.12": + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.12.tgz#0c5f6a0050af4a6b7384a6d3dcb34a8f496ea58a" + integrity sha512-T2YWPPgj6voKowx9YanPTaFqPatxfBR3oVm/uPtt2iRFvt8POy1wYWBBzjFHRJKicQflhA2LEfHWFr82xyzCCg== dependencies: - "@babylonjs/core" "4.1.0-beta.9" - babylonjs-gltf2interface "4.1.0-beta.9" + "@babylonjs/core" "4.1.0-beta.12" + babylonjs-gltf2interface "4.1.0-beta.12" tslib "^1.10.0" "@cnakazawa/watch@^1.0.3": @@ -2217,15 +2217,15 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -babylonjs-gltf2interface@4.1.0-beta.9: - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.9.tgz#43238e5ac6b2d84554a9b99527fc626c160d0fce" - integrity sha512-aTsoK6cLBVguU5DlgBvRbiti4G5ItumbnYbLvcQr5IbG9xuPeca01N70QxTB1OWjNiGkq0+tlIqsrQg3J9xBgQ== +babylonjs-gltf2interface@4.1.0-beta.12: + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.12.tgz#38dbc4d3b48e76d4b29d9508092d62eb17e4ae26" + integrity sha512-BOLX7C2elDVd9UtJXPnOF7qMCy7LebtpySCEnhlsZDvCIVWqBhQgzXA/d3Oeb4tGtpiZtaB87WG2bzuLWL0FzA== -babylonjs@4.1.0-beta.9: - version "4.1.0-beta.9" - resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.9.tgz#1d2345ce0b17917383c31f64072fea8b89cbb94a" - integrity sha512-5B8+ESAc1WsdOjfml0Amm8SVdSeCLv6HFmcVxQZCE6ftNhNvN+UkN+OILTIZ9LvdPoslOntY/Ow7PNAyIZ/vSw== +babylonjs@4.1.0-beta.12: + version "4.1.0-beta.12" + resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.12.tgz#f42d88d865c9ba984506afde3b054dec215af092" + integrity sha512-SyQVqarSuBDAmIkIzGctb35XSwuRAv+vI9CaE5rz4ls35pbvPdj0Nf3sZUePUDw6CZueRp3z2sL+zgPuvbg3Ow== bail@^1.0.0: version "1.0.4" From 38002fb93d726ffbf8dccb6b1e4418586ec9c5ca Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 12 Dec 2019 17:55:06 +0100 Subject: [PATCH 20/67] build(github): keep `develop` after PR merge --- .github/delete-merged-branch-config.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/delete-merged-branch-config.yml diff --git a/.github/delete-merged-branch-config.yml b/.github/delete-merged-branch-config.yml new file mode 100644 index 00000000..bf332d23 --- /dev/null +++ b/.github/delete-merged-branch-config.yml @@ -0,0 +1,3 @@ +exclude: + - master + - develop From 2e5f6b3bedc3507d52ec2867dc32e0093a486e14 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Mon, 16 Dec 2019 11:25:39 +0100 Subject: [PATCH 21/67] build(dep): `cypress` to `v3.8.0` --- .circleci/config.yml | 2 +- README.md | 3 +++ package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d3a2873e..121bad2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ aliases: # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included docker: - - image: cypress/included:3.7.0 + - image: cypress/included:3.8.0 - &workspace ~/talus diff --git a/README.md b/README.md index 90bd6c28..25a41e36 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,9 @@ Setting up a macro which will fix all the linting issues, optimizes the imports installed in order to be able to run Cypress locally. - `yarn e2e ` +When updating Cypress version in `package.json` the version in `.circleci/config.yml` needs to be +updated as well. + ## Nx ### Update diff --git a/package.json b/package.json index 9549c7db..3e32cdc5 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "babylonjs": "4.1.0-beta.12", "benchmark": "2.1.4", "codelyzer": "5.2.0", - "cypress": "3.7.0", + "cypress": "3.8.0", "dotenv": "8.2.0", "gh-pages": "2.1.1", "jasmine-marbles": "0.6.0", diff --git a/yarn.lock b/yarn.lock index fcfbc79b..922e1a2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3339,10 +3339,10 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress@3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.7.0.tgz#e2cd71b87b6ce0d4c72c6ea25da1005d75c1f231" - integrity sha512-o+vfRxqAba8TduelzfZQ4WHmj2yNEjaoO2EuZ8dZ9pJpuW+WGtBGheKIp6zkoQsp8ZgFe8OoHh1i2mY8BDnMAw== +cypress@3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.0.tgz#7d4cd08f81f9048ee36760cc9ee3b9014f9e84ab" + integrity sha512-gtEbqCgKETRc3pQFMsELRgIBNgiQg7vbOWTrCi7WE7bgOwNCaW9PEX8Jb3UN8z/maIp9WwzoFfeySfelYY7nRA== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" From 9629429e00bfb6d055d5a7e0408a28738f0625a6 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Mon, 16 Dec 2019 13:09:54 +0100 Subject: [PATCH 22/67] build(dep): `cypress` to `v3.7.0` --- .circleci/config.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 121bad2b..d3a2873e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ aliases: # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included docker: - - image: cypress/included:3.8.0 + - image: cypress/included:3.7.0 - &workspace ~/talus diff --git a/package.json b/package.json index 3e32cdc5..9549c7db 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "babylonjs": "4.1.0-beta.12", "benchmark": "2.1.4", "codelyzer": "5.2.0", - "cypress": "3.8.0", + "cypress": "3.7.0", "dotenv": "8.2.0", "gh-pages": "2.1.1", "jasmine-marbles": "0.6.0", From bb5440f8178ee7bdbb170100e5d2196e8d15ac15 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 17 Dec 2019 12:02:17 +0100 Subject: [PATCH 23/67] test(vdb): set value with float coordinates: - coordinates get always rounded down --- libs/vdb/src/lib/tree/root-node.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/vdb/src/lib/tree/root-node.spec.ts b/libs/vdb/src/lib/tree/root-node.spec.ts index d3e07462..a4b37e17 100644 --- a/libs/vdb/src/lib/tree/root-node.spec.ts +++ b/libs/vdb/src/lib/tree/root-node.spec.ts @@ -17,6 +17,23 @@ describe('RootNode', () => { expect(root.getValue([1, 1, 1])).toEqual(-1); }); + + it('should set value when given float coordinates', () => { + const root = new RootNode(-1); + + root.setValueOn([0, 0, 0.1], 1); + root.setValueOn([0, 1.5, 0], 5); + root.setValueOn([2.9, 0, 0], 9); + + expect(root.getValue([0, 0, 0])).toEqual(1); + expect(root.getValue([0, 0, 1])).toEqual(-1); + + expect(root.getValue([0, 1, 0])).toEqual(5); + expect(root.getValue([0, 2, 0])).toEqual(-1); + + expect(root.getValue([2, 0, 0])).toEqual(9); + expect(root.getValue([3, 0, 0])).toEqual(-1); + }); }); describe('onVoxelCount()', () => { From 1362079a30777b1321b7a73135cc7b7ff8dfdf88 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Tue, 17 Dec 2019 15:01:05 +0100 Subject: [PATCH 24/67] build(dep): `cypress` to `v3.7.0` --- .circleci/config.yml | 1 + yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d3a2873e..6ec44143 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,6 +16,7 @@ aliases: # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included docker: + # 3.8.0 fails with `Error: write EPIPE` when running `benchmark`!? - image: cypress/included:3.7.0 - &workspace ~/talus diff --git a/yarn.lock b/yarn.lock index 922e1a2e..fcfbc79b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3339,10 +3339,10 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress@3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.0.tgz#7d4cd08f81f9048ee36760cc9ee3b9014f9e84ab" - integrity sha512-gtEbqCgKETRc3pQFMsELRgIBNgiQg7vbOWTrCi7WE7bgOwNCaW9PEX8Jb3UN8z/maIp9WwzoFfeySfelYY7nRA== +cypress@3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.7.0.tgz#e2cd71b87b6ce0d4c72c6ea25da1005d75c1f231" + integrity sha512-o+vfRxqAba8TduelzfZQ4WHmj2yNEjaoO2EuZ8dZ9pJpuW+WGtBGheKIp6zkoQsp8ZgFe8OoHh1i2mY8BDnMAw== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" From e8cd3c929f9a6a76526cf0555fbd87ef4bac15af Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 18 Dec 2019 18:09:50 +0100 Subject: [PATCH 25/67] feat(frontend): support adding and removing voxels --- .../scene-viewer-container/grid.service.ts | 2 +- .../scene-viewer-container.component.spec.ts | 133 ++++++++++++++---- .../scene-viewer-container.component.ts | 61 +++++++- .../lib/scene-viewer/scene-viewer.service.ts | 20 +-- libs/vdb/src/lib/tools/grid-to-mesh.ts | 12 +- libs/vdb/src/lib/tree/root-node.spec.ts | 10 +- 6 files changed, 190 insertions(+), 48 deletions(-) diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index bf5474c9..4b2d47c9 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -20,7 +20,7 @@ export class GridService { this.accessor.setValueOff(xyz, this.grid.background); } - computeMesh(): MeshData { + computeMesh(): MeshData | undefined { return gridToMesh(this.grid); } } diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 43243d9e..358f8234 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -4,6 +4,7 @@ import { By } from '@angular/platform-browser'; import { MemoizedSelector, Store } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { PointerButton, PointerPickInfo } from '@talus/ui'; +import { Coord } from '@talus/vdb'; import { Subject } from 'rxjs'; import * as fromApp from '../app.reducer'; import { Tool } from '../tools-panel/tool.model'; @@ -68,31 +69,109 @@ describe('SceneViewerContainerComponent', () => { expect(mockStore.dispatch).not.toHaveBeenCalled(); }); - it('should dispatch `addVoxel` action', () => { - const action = addVoxel({ position: [1, 1, 1], value: 42 }); - - stubComponent.pointerPick.next({ - pickedPoint: [1, 1, 1], - pointerButton: PointerButton.Main, - normal: [0, 0, 1], - }); - - expect(mockStore.dispatch).toHaveBeenCalledWith(action); - }); - - it('should dispatch `removeVoxel` action', () => { - mockSelectedToolIdSelector.setResult(Tool.RemoveVoxel); - mockStore.refreshState(); - fixture.detectChanges(); - - const action = removeVoxel({ position: [1, 1, 1] }); - - stubComponent.pointerPick.next({ - pickedPoint: [1, 1, 1], - pointerButton: PointerButton.Main, - normal: [0, 0, 1], - }); - - expect(mockStore.dispatch).toHaveBeenCalledWith(action); - }); + it.each([ + [ + [1, 0.2, 0.9], + [1, 0.2, 0.9], + [1, 0, 0], + ], + [ + [0.99999999, 0.2, 0.9], + [1, 0.2, 0.9], + [1, 0, 0], + ], + [ + [0.2, 0.99999999, 0.9], + [0.2, 1, 0.9], + [0, 1, 0], + ], + [ + [0.2, 0.9, 0.0000000001], + [0.2, 0.9, 0], + [0, 0, 1], + ], + [ + [0, 0, -0.999999], + [0, 0, -2], + [0, 0, 1], + ], + [ + [0, -2, -0.999999], + [0, -3, -2], + [0, 0, -1], + ], + [ + [-0, -2, 3], + [-0, -3, 2], + [0, 0, -1], + ], + ])( + 'should dispatch `addVoxel` action for %j', + (pickedPoint: Coord, position: Coord, normal: Coord) => { + const action = addVoxel({ position, value: 42 }); + + stubComponent.pointerPick.next({ + pickedPoint, + pointerButton: PointerButton.Main, + normal, + }); + + expect(mockStore.dispatch).toHaveBeenCalledWith(action); + }, + ); + + it.each([ + [ + [1.0000000000001, 0.5, 0.5], + [0, 0.5, 0.5], + [1, 0, 0], + ], + [ + [0.999999999999, 0.5, 0.5], + [1, 0.5, 0.5], + [-1, 0, 0], + ], + [ + [1.0000000000001, -0.5, 0.5], + [1, -1.5, 0.5], + [-1, 0, 0], + ], + [ + [-0.999999999999, -0.5, 0.5], + [-1, -1.5, 0.5], + [-1, 0, 0], + ], + [ + [-2.0000000000001, -0.5, 0.5], + [-3, -1.5, 0.5], + [1, 0, 0], + ], + [ + [0.5, 0.999999999999, 0.5], + [0.5, 0, 0.5], + [0, 1, 0], + ], + [ + [0.5461420538559825, 0.4841910809236776, -2], + [0.5461420538559825, 0.4841910809236776, -2], + [0, 0, -1], + ], + ])( + 'should dispatch `removeVoxel` action for %j', + (pickedPoint: Coord, position: Coord, normal: Coord) => { + mockSelectedToolIdSelector.setResult(Tool.RemoveVoxel); + mockStore.refreshState(); + fixture.detectChanges(); + + const action = removeVoxel({ position }); + + stubComponent.pointerPick.next({ + pickedPoint, + pointerButton: PointerButton.Main, + normal, + }); + + expect(mockStore.dispatch).toHaveBeenCalledWith(action); + }, + ); }); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index 8220529f..fc39f4ef 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -3,7 +3,7 @@ import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; // import '@babylonjs/core/Rendering/outlineRenderer'; import { select, Store } from '@ngrx/store'; import { PointerButton, PointerPickInfo, SceneViewerComponent } from '@talus/ui'; -import { add, Coord } from '@talus/vdb'; +import { Coord } from '@talus/vdb'; import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; import { Tool } from '../tools-panel/tool.model'; @@ -44,15 +44,66 @@ export class SceneViewerContainerComponent { switch (selectedToolId) { case Tool.AddVoxel: - this.store.dispatch(addVoxel({ position: pickInfo.pickedPoint, value: 42 })); + this.store.dispatch( + addVoxel({ position: this.calcVoxelToAddPosition(pickInfo), value: 42 }), + ); break; case Tool.RemoveVoxel: - this.store.dispatch(removeVoxel({ position: pickInfo.pickedPoint })); + this.store.dispatch(removeVoxel({ position: this.calcVoxelToRemovePosition(pickInfo) })); break; } } - private calcNewVoxelPosition(pickInfo: PointerPickInfo): Coord { - return add(pickInfo.pickedPoint, pickInfo.normal); + private calcVoxelToAddPosition(pickInfo: PointerPickInfo): Coord { + const pickedIntegerPoint = this.roundDimensionAlongNormal(pickInfo); + + const newPoint: Coord = [ + pickedIntegerPoint[0] < 0 || pickInfo.normal[0] < 0 + ? pickedIntegerPoint[0] - 1 + : pickedIntegerPoint[0], + pickedIntegerPoint[1] < 0 || pickInfo.normal[1] < 0 + ? pickedIntegerPoint[1] - 1 + : pickedIntegerPoint[1], + pickedIntegerPoint[2] < 0 || pickInfo.normal[2] < 0 + ? pickedIntegerPoint[2] - 1 + : pickedIntegerPoint[2], + ]; + + return newPoint; + } + + private calcVoxelToRemovePosition(pickInfo: PointerPickInfo): Coord { + const pickedIntegerPoint = this.roundDimensionAlongNormal(pickInfo); + + const newPoint: Coord = [ + pickInfo.normal[0] > 0 || (pickInfo.normal[0] === 0 && pickedIntegerPoint[0] < 0) + ? pickedIntegerPoint[0] - 1 + : pickedIntegerPoint[0], + pickInfo.normal[1] > 0 || (pickInfo.normal[1] === 0 && pickedIntegerPoint[1] < 0) + ? pickedIntegerPoint[1] - 1 + : pickedIntegerPoint[1], + pickInfo.normal[2] > 0 || (pickInfo.normal[2] === 0 && pickedIntegerPoint[2] < 0) + ? pickedIntegerPoint[2] - 1 + : pickedIntegerPoint[2], + ]; + + return newPoint; + } + + /** + * Babylon.js returns sometimes a floating instead of integer number for the dimension of + * the normal vector of the picked point. + * E.g. Click on [1, 0.5, 0.6] on voxel at [0, 0, 0] on its site which has the x-axis as its + * normal vector [1, 0, 0], could result in a picking point of something like [0.99999, 0.5, 0.6]. + * Where in fact it should be [1, 0.5, 0.6]. + * Since all the voxels are placed on integer positions the dimension of the picked point + * needs to be rounded. + */ + private roundDimensionAlongNormal(pickInfo: PointerPickInfo): Coord { + return [ + pickInfo.normal[0] !== 0 ? Math.round(pickInfo.pickedPoint[0]) : pickInfo.pickedPoint[0], + pickInfo.normal[1] !== 0 ? Math.round(pickInfo.pickedPoint[1]) : pickInfo.pickedPoint[1], + pickInfo.normal[2] !== 0 ? Math.round(pickInfo.pickedPoint[2]) : pickInfo.pickedPoint[2], + ]; } } diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 4de11939..1ffeb152 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -86,18 +86,20 @@ export class SceneViewerService { this.engine.resize(); } - updateGridMesh(mesh: MeshData): void { + updateGridMesh(mesh?: MeshData): void { this.scene.removeMesh(this.gridMesh); - this.gridMesh = new Mesh('grid', this.scene); - const data = new VertexData(); + if (mesh) { + this.gridMesh = new Mesh('grid', this.scene); + const data = new VertexData(); - data.colors = mesh.colors; - data.indices = mesh.indices; - data.positions = mesh.positions; + data.colors = mesh.colors; + data.indices = mesh.indices; + data.positions = mesh.positions; - data.applyToMesh(this.gridMesh); - this.gridMesh.convertToFlatShadedMesh(); + data.applyToMesh(this.gridMesh); + this.gridMesh.convertToFlatShadedMesh(); + } } private createCamera(): void { @@ -121,7 +123,7 @@ export class SceneViewerService { } private createLight(): void { - this.light = new HemisphericLight('light', new Vector3(0, 1, -1), this.scene); + this.light = new HemisphericLight('light', new Vector3(0, 1, -2), this.scene); } private registerPointerPick(): void { diff --git a/libs/vdb/src/lib/tools/grid-to-mesh.ts b/libs/vdb/src/lib/tools/grid-to-mesh.ts index 84f6f377..fe5218ec 100644 --- a/libs/vdb/src/lib/tools/grid-to-mesh.ts +++ b/libs/vdb/src/lib/tools/grid-to-mesh.ts @@ -23,11 +23,15 @@ export interface MeshData { positions: number[]; } -export function gridToMesh(grid: Grid): MeshData { +/** + * Returns a mesh if there are any active voxels saved in the grid. + * Otherwise, returns `undefined` i.e. if there are no active voxels. + */ +export function gridToMesh(grid: Grid): MeshData | undefined { const mesh: MeshData = { - positions: [], - indices: [], colors: [], + indices: [], + positions: [], // normals: [], }; @@ -76,5 +80,5 @@ export function gridToMesh(grid: Grid): MeshData { mesh.colors.push(0, 1, 0, 1); } - return mesh; + return vertexCount !== 0 ? mesh : undefined; } diff --git a/libs/vdb/src/lib/tree/root-node.spec.ts b/libs/vdb/src/lib/tree/root-node.spec.ts index a4b37e17..6ee42d90 100644 --- a/libs/vdb/src/lib/tree/root-node.spec.ts +++ b/libs/vdb/src/lib/tree/root-node.spec.ts @@ -27,12 +27,18 @@ describe('RootNode', () => { expect(root.getValue([0, 0, 0])).toEqual(1); expect(root.getValue([0, 0, 1])).toEqual(-1); - expect(root.getValue([0, 1, 0])).toEqual(5); expect(root.getValue([0, 2, 0])).toEqual(-1); - expect(root.getValue([2, 0, 0])).toEqual(9); expect(root.getValue([3, 0, 0])).toEqual(-1); + + root.setValueOn([0, 0, -1.2], -2); + root.setValueOn([0, -2.5, 0], -5); + root.setValueOn([-3.9, 0, 0], -9); + + expect(root.getValue([0, 0, -1])).toEqual(-2); + expect(root.getValue([0, -2, 0])).toEqual(-5); + expect(root.getValue([-3, 0, 0])).toEqual(-9); }); }); From 97ff0c6a634fe8b844b89579a0d01e662ed66d76 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 10:25:19 +0100 Subject: [PATCH 26/67] test(ui): remove unused imported components --- .../lib/sidenav-shell/sidenav-shell.component.spec.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts index 6830ad8e..3d684bf3 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts @@ -1,14 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatButtonModule, MatIconModule, MatSidenavModule } from '@angular/material'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { SidenavShellModule } from '@talus/ui'; -import { - SidenavShellComponent, - SidenavShellContentComponent, - SidenavShellLeftComponent, - SidenavShellRightComponent, -} from './sidenav-shell.component'; +import { SidenavShellComponent } from './sidenav-shell.component'; +import { SidenavShellModule } from './sidenav-shell.module'; describe('SidenavShellComponent', () => { let component: SidenavShellComponent; From b041d82977d5d0f5a55db3be94f19a303dcea9c2 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 10:33:44 +0100 Subject: [PATCH 27/67] build(CircleCi): use `13.3.0` due failing tests: - Test suite failed to run - Call retries were exceeded at ChildProcessWorker.initialize() - https://github.com/jest-community/vscode-jest/issues/486#issuecomment-563164125 --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ec44143..172ede23 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,11 +7,11 @@ aliases: # https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/node/images - &use_docker_node docker: - - image: circleci/node:13.2.0-stretch + - image: circleci/node:13.3.0-stretch - &use_docker_node_browsers docker: - - image: circleci/node:13.2.0-stretch-browsers + - image: circleci/node:13.3.0-stretch-browsers # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included From a96dfed85c99c21fdc81ee5a1ce1cdcf8f6851c3 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 11:01:58 +0100 Subject: [PATCH 28/67] fix(frontend): add voxel on positive normal - but negative position --- .../scene-viewer-container.component.spec.ts | 7 ++++++- .../scene-viewer-container.component.ts | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 358f8234..cc914e18 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -92,7 +92,7 @@ describe('SceneViewerContainerComponent', () => { ], [ [0, 0, -0.999999], - [0, 0, -2], + [0, 0, -1], [0, 0, 1], ], [ @@ -105,6 +105,11 @@ describe('SceneViewerContainerComponent', () => { [-0, -3, 2], [0, 0, -1], ], + [ + [0.5, 1.4, -1], + [0.5, 1.4, -1], + [0, 0, 1], + ], ])( 'should dispatch `addVoxel` action for %j', (pickedPoint: Coord, position: Coord, normal: Coord) => { diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index fc39f4ef..d9efee4c 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -57,14 +57,18 @@ export class SceneViewerContainerComponent { private calcVoxelToAddPosition(pickInfo: PointerPickInfo): Coord { const pickedIntegerPoint = this.roundDimensionAlongNormal(pickInfo); + // VDB removes fractional-part of the coordinate, i.e. 0.54 -> 0. + // Therefore, positive numbers are getting rounded down (1.9 -> 1) and + // negative numbers are getting rounded up (-0.2 -> 0). + // Hence, the subtraction of 1 is needed. const newPoint: Coord = [ - pickedIntegerPoint[0] < 0 || pickInfo.normal[0] < 0 + pickInfo.normal[0] < 0 || (pickInfo.normal[0] === 0 && pickedIntegerPoint[0] < 0) ? pickedIntegerPoint[0] - 1 : pickedIntegerPoint[0], - pickedIntegerPoint[1] < 0 || pickInfo.normal[1] < 0 + pickInfo.normal[1] < 0 || (pickInfo.normal[1] === 0 && pickedIntegerPoint[1] < 0) ? pickedIntegerPoint[1] - 1 : pickedIntegerPoint[1], - pickedIntegerPoint[2] < 0 || pickInfo.normal[2] < 0 + pickInfo.normal[2] < 0 || (pickInfo.normal[2] === 0 && pickedIntegerPoint[2] < 0) ? pickedIntegerPoint[2] - 1 : pickedIntegerPoint[2], ]; From 575e9db8e8abb95ce17e538ee937c82cdcad1285 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 11:56:47 +0100 Subject: [PATCH 29/67] test(frontend): set `setupFilesAfterEnv` - to run in Jest tests within WebStorm - https://github.com/nrwl/nx/issues/1439#issuecomment-561268656 --- apps/frontend/jest.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/frontend/jest.config.js b/apps/frontend/jest.config.js index a577bddd..fcec8211 100644 --- a/apps/frontend/jest.config.js +++ b/apps/frontend/jest.config.js @@ -19,4 +19,8 @@ module.exports = { 'jest-preset-angular/AngularSnapshotSerializer.js', 'jest-preset-angular/HTMLCommentSerializer.js', ], + // https://github.com/nrwl/nx/issues/1439#issuecomment-561268656 + // When using `Run test` directly in WebStorm, change the used config to + // this file i.e. `./frontend/jest.config.js` and not `/jest.config.js`. + setupFilesAfterEnv: ['./src/test-setup.ts'], }; From 596f386946c7d3a969dc19105a352a5d654dd1e2 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 12:40:26 +0100 Subject: [PATCH 30/67] test(frontend): set `globals`>`tsConfig` - to run in Jest tests within WebStorm with SCSS imports in component --- jest.config.js | 3 --- libs/ui/jest.config.js | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/jest.config.js b/jest.config.js index 97fc9385..4f64d597 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,3 @@ -// const ignoreLibs = ['@babylonjs/core']; - module.exports = { testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'], transform: { @@ -11,5 +9,4 @@ module.exports = { moduleNameMapper: { '@babylonjs': 'babylonjs', }, - // transformIgnorePatterns: [`/node_modules/(?!(${ignoreLibs.join('|')})/)`], }; diff --git a/libs/ui/jest.config.js b/libs/ui/jest.config.js index 5c7b5a4e..35d35ffa 100644 --- a/libs/ui/jest.config.js +++ b/libs/ui/jest.config.js @@ -19,4 +19,23 @@ module.exports = { 'jest-preset-angular/AngularSnapshotSerializer.js', 'jest-preset-angular/HTMLCommentSerializer.js', ], + // https://github.com/nrwl/nx/issues/1439#issuecomment-561268656 + // When using `Run test` directly in WebStorm, change the used config to + // this file i.e. `./ui/jest.config.js` and not `/jest.config.js`. + // Otherwise, following error might occur: + // - Cannot find module '@talus/ui' + // - Zone is needed for the async() test helper but could not be found. + setupFilesAfterEnv: ['./src/test-setup.ts'], + + // https://github.com/thymikee/jest-preset-angular/issues/293#issuecomment-513544717 + // When using `Run test` directly in WebStorm, the scss couldn't be loaded. + // - Error: connect ECONNREFUSED 127.0.0.1:80 + // - Error: Uncaught (in promise): Failed to load *.component.scss + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.spec.json', + // stringifyContentPathRegex: '\\.html$', + // astTransformers: [require.resolve('jest-preset-angular/InlineHtmlStripStylesTransformer')], + }, + }, }; From c1ddf8398156fe8cf5b5bdacb48bb4420eb978da Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 14:09:16 +0100 Subject: [PATCH 31/67] build(CircleCi): use `13.4.0` --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 172ede23..854fadfc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,11 +7,11 @@ aliases: # https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/node/images - &use_docker_node docker: - - image: circleci/node:13.3.0-stretch + - image: circleci/node:13.4.0-stretch - &use_docker_node_browsers docker: - - image: circleci/node:13.3.0-stretch-browsers + - image: circleci/node:13.4.0-stretch-browsers # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included From 3726648eb4a46af90600984e78169701109897b9 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 19 Dec 2019 14:31:27 +0100 Subject: [PATCH 32/67] build(dep): update diverse dependencies: - @ngrx/effects, @ngrx/store - core-js, mnemonist, codelyzer - @types/jest, @types/node --- package.json | 14 ++++++------ yarn.lock | 60 ++++++++++++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index 9549c7db..050420e9 100644 --- a/package.json +++ b/package.json @@ -46,12 +46,12 @@ "@angular/router": "8.2.14", "@babylonjs/core": "4.1.0-beta.12", "@babylonjs/materials": "4.1.0-beta.12", - "@ngrx/effects": "8.5.2", - "@ngrx/store": "8.5.2", + "@ngrx/effects": "8.6.0", + "@ngrx/store": "8.6.0", "@nrwl/angular": "8.9.0", - "core-js": "3.5.0", + "core-js": "3.6.0", "hammerjs": "2.0.8", - "mnemonist": "0.31.3", + "mnemonist": "0.32.0", "rxjs": "6.5.3", "zone.js": "0.10.2" }, @@ -66,11 +66,11 @@ "@nrwl/node": "8.9.0", "@nrwl/workspace": "8.9.0", "@types/benchmark": "1.0.31", - "@types/jest": "24.0.23", - "@types/node": "12.12.17", + "@types/jest": "24.0.24", + "@types/node": "12.12.21", "babylonjs": "4.1.0-beta.12", "benchmark": "2.1.4", - "codelyzer": "5.2.0", + "codelyzer": "5.2.1", "cypress": "3.7.0", "dotenv": "8.2.0", "gh-pages": "2.1.1", diff --git a/yarn.lock b/yarn.lock index fcfbc79b..a5f22d7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1162,15 +1162,15 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@ngrx/effects@8.5.2": - version "8.5.2" - resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-8.5.2.tgz#c4f81947f4028a0d678ed2641101481cdbe11b59" - integrity sha512-i2rKLmFcfJmPPQRul1PuXXRuBX2q1g7tK6DbWreNabU/46fYlEwqiiW6lU53t3AgJ3yd6UpeLTR6CHTflkzL+w== +"@ngrx/effects@8.6.0": + version "8.6.0" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-8.6.0.tgz#a0d7339597a5128c5cf896ddcf93f73406a45860" + integrity sha512-JdyJLQbv/wnE0ZPY9DcDOtF9PzJuzsKWmIWgIGunHF18wdjk5O8Zpkcrxq18wDRL6geg5UTtNJRMvTQhpDbzow== -"@ngrx/store@8.5.2": - version "8.5.2" - resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-8.5.2.tgz#18e4a39f3e7ac2ec8307653837ec3c4153bde04f" - integrity sha512-JPlc23Aw3rlEKt6LCkg3a0zlo0tEgkohH3CDHVbUIYSgg3DWOnmNfwztbz4pa2u2wua5PfFCovC7HKTNmapx/w== +"@ngrx/store@8.6.0": + version "8.6.0" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-8.6.0.tgz#8540c5bd40b33fc2f443e7e86f47c0d801b8f413" + integrity sha512-K4cvCEa+5hw9qrETQWO+Cha3YbVCAT8yaIKJr/N35KntTL9mQMjoL+51JWLZfBwPV0e19CFgJIyrBnVUTxwr2A== "@ngtools/webpack@8.3.20": version "8.3.20" @@ -1405,10 +1405,10 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@24.0.23": - version "24.0.23" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.23.tgz#046f8e2ade026fe831623e361a36b6fb9a4463e4" - integrity sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg== +"@types/jest@24.0.24": + version "24.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.24.tgz#0f2f523dc77cc1bc6bef34eaf287ede887a73f05" + integrity sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ== dependencies: jest-diff "^24.3.0" @@ -1427,10 +1427,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== -"@types/node@12.12.17": - version "12.12.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b" - integrity sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA== +"@types/node@12.12.21": + version "12.12.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" + integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== "@types/parse-json@^4.0.0": version "4.0.0" @@ -2076,7 +2076,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -axobject-query@^2.0.2: +axobject-query@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== @@ -2934,14 +2934,14 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codelyzer@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.2.0.tgz#b0ee573a12779c996090e596c5c1755479d83758" - integrity sha512-izfUfhEOOgAizszPlEDxo71DK/C4wprZw0vkY6UWcOSTQvN1JyfXf9DXwaV7WX+/JC+hH0ShXfdtGLA9Rca7LA== +codelyzer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.2.1.tgz#44fd431e128009f38c761828c33ebacba9549d32" + integrity sha512-awBZXFcJUyC5HMYXiHzjr3D24tww2l1D1OqtfA9vUhEtYr32a65A+Gblm/OvsO+HuKLYzn8EDMw1inSM3VbxWA== dependencies: app-root-path "^2.2.1" aria-query "^3.0.0" - axobject-query "^2.0.2" + axobject-query "2.0.2" css-selector-tokenizer "^0.7.1" cssauron "^1.4.0" damerau-levenshtein "^1.0.4" @@ -3170,10 +3170,10 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.5.0.tgz#66df8e49be4bd775e6f952a9d083b756ad41c1ed" - integrity sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw== +core-js@3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.0.tgz#2b854e451de1967d1e29896025cdc13a2518d9ea" + integrity sha512-AHPTNKzyB+YwgDWoSOCaid9PUSEF6781vsfiK8qUz62zRR448/XgK2NtCbpiUGizbep8Lrpt0Du19PpGGZvw3Q== core-js@^2.4.0: version "2.6.9" @@ -6863,10 +6863,10 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -mnemonist@0.31.3: - version "0.31.3" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.31.3.tgz#bb2857ad8c00891c23684af67d7ad39676780178" - integrity sha512-COyTIeUNrltQ5e08mxkJmzagJF6c6vwYl2dI6DtsH8qtutFEgoIsJ/jqXtS57M52DreGKVtOusINzDRk2r3YMA== +mnemonist@0.32.0: + version "0.32.0" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.32.0.tgz#2c6d1dd12cb69ca2ed79a636ba9ffe5a6e9f2573" + integrity sha512-WMVGPpT8guWwnsnw+WibOvInBnPfXFG+9SD+mg2+YgPEuW9Gdz9D2MEi05ko6RG1ui0RHljc+yYAvOHQn3GbbQ== dependencies: obliterator "^1.5.0" From 4d690b9c6a7896d8ba04df9c384ebfda9cc090d4 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Fri, 20 Dec 2019 11:54:28 +0100 Subject: [PATCH 33/67] doc(readme): record macro & git setup --- README.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 25a41e36..06a8e3e4 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,18 @@ This project was generated using [Nx](https://nx.dev) with the following command - https://github.com/nvm-sh/nvm#installation-and-update 2. Install (latest) `node` - `nvm install node` - - or add a version `nvm install 12.3.1` - - set a version as default `nvm alias default 12.3.1` + - or add a version `nvm install 13.4.0` + - set a version as default `nvm alias default 13.4.0` ### Yarn +#### Manually + +1. Install `yarn` + - https://yarnpkg.com/lang/en/docs/install/#debian-stable + +#### With brew + 1. Install `yarn` - `brew install yarn` 2. Update @@ -94,17 +101,33 @@ Setting up a macro which will fix all the linting issues, optimizes the imports - Working Dir: `$FileDir$` - Advanced Options: None, all deactivated -2. Record macro in this order +2. Record macro (Edit > Macros > Start Macro Recording) in this order - - Action: TsLintFileFixAction + - Action: TsLintFileFixAction (with opened \*.ts file) - Action: OptimizeImports - Action: ReformatWithPrettierAction - - Action: FileWatcher.runForFiles + - Action: FileWatcher.runForFiles (with opened \*.scss file) - Action: SaveAll 3. Save macro as e.g. `Fix & Save` -4. Assign Keyboard shortcut `Ctrl` + `S` to macro `Fix & Save` +4. Assign Keyboard shortcut `Ctrl` + `S` to macro `Fix & Save` (search for macro) + +### Git + +1. Make sure that `git-completion` is working, otherwise run: + `sudo apt-get install git-core bash-completion` + +2. Add branch name to shell + - Download & save + [git-prompt.sh](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh) + - Add in `.bashrc`: + ``` + # GIT prompt + . ~/Projects/git-prompt.sh + export GIT_PS1_SHOWDIRTYSTATE=1 + export PS1='\[\e[1;32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\]:\[\e[34m\]\w\[\e[m\]$(__git_ps1 " (%s)")\$ ' + ``` ## Build From 2a3f37ab55ce135f598865f97bd8121f31539fb6 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Fri, 20 Dec 2019 13:54:17 +0100 Subject: [PATCH 34/67] build(dep): `@angular-devkit/build-angular` & `@angular/cli` --- package.json | 4 +- yarn.lock | 857 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 783 insertions(+), 78 deletions(-) diff --git a/package.json b/package.json index 050420e9..dd0b33a6 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,8 @@ "zone.js": "0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "0.803.20", - "@angular/cli": "8.3.20", + "@angular-devkit/build-angular": "0.803.21", + "@angular/cli": "8.3.21", "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", "@babylonjs/inspector": "4.1.0-beta.12", diff --git a/yarn.lock b/yarn.lock index a5f22d7a..1d45ac82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,26 +10,26 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/architect@0.803.20": - version "0.803.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.803.20.tgz#792093259d69012c0763aa9176181b255d8795c8" - integrity sha512-NjyDJ61i9kh8J+qXt0E2j+P5Xsmi2mPasBzwcQyrZZGiho4zC0IFxcdxyzcsXFEupmilJKkjdt2g4QQRC5rUDQ== +"@angular-devkit/architect@0.803.21": + version "0.803.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.803.21.tgz#0e76b6f646ebdbd9bb88d3972b2ca66fed950f7d" + integrity sha512-E2K/YexIWVyKM/xmyxvDjkJf+wX9u4c8YYpNaK4htsRzA06juc7N1MhlL/jURZiRl5b/K9sapYeq3tMX76saxA== dependencies: - "@angular-devkit/core" "8.3.20" + "@angular-devkit/core" "8.3.21" rxjs "6.4.0" -"@angular-devkit/build-angular@0.803.20": - version "0.803.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.803.20.tgz#b19b0d82c75cbdd939b589a33ccb60e2c9f6eec9" - integrity sha512-JDZkZjOqPbOtCMsSKxQf9C+uSTZ7fQGlKGsCpJMzfa4iQ0WrmrhZvnRKQeEpMTTZTpuou/HQeQjyDV+Sx3yumw== - dependencies: - "@angular-devkit/architect" "0.803.20" - "@angular-devkit/build-optimizer" "0.803.20" - "@angular-devkit/build-webpack" "0.803.20" - "@angular-devkit/core" "8.3.20" - "@babel/core" "7.5.5" - "@babel/preset-env" "7.5.5" - "@ngtools/webpack" "8.3.20" +"@angular-devkit/build-angular@0.803.21": + version "0.803.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.803.21.tgz#f3d12ea09748b05eb2d835a7de7997599fb6b752" + integrity sha512-flfgflvfpwdsm3x/U7QnfbtyZPEbsVipzQAoao1Zo58Beq1a+NsKsWbjrF/x4TSoI2czt0OVWXNytlfXM7LMhg== + dependencies: + "@angular-devkit/architect" "0.803.21" + "@angular-devkit/build-optimizer" "0.803.21" + "@angular-devkit/build-webpack" "0.803.21" + "@angular-devkit/core" "8.3.21" + "@babel/core" "7.7.5" + "@babel/preset-env" "7.7.6" + "@ngtools/webpack" "8.3.21" ajv "6.10.2" autoprefixer "9.6.1" browserslist "4.6.6" @@ -37,7 +37,7 @@ caniuse-lite "1.0.30000989" circular-dependency-plugin "5.2.0" clean-css "4.2.1" - copy-webpack-plugin "5.0.4" + copy-webpack-plugin "5.1.1" core-js "3.2.1" file-loader "4.2.0" find-cache-dir "3.0.0" @@ -70,7 +70,7 @@ stylus "0.54.5" stylus-loader "3.0.2" terser "4.3.9" - terser-webpack-plugin "1.4.1" + terser-webpack-plugin "1.4.3" tree-kill "1.2.1" webpack "4.39.2" webpack-dev-middleware "3.7.2" @@ -80,10 +80,10 @@ webpack-subresource-integrity "1.1.0-rc.6" worker-plugin "3.2.0" -"@angular-devkit/build-optimizer@0.803.20": - version "0.803.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.803.20.tgz#36f92c350c1cb3d3d7f1e0f0086feed726478902" - integrity sha512-Vzxf1g1EuzaPBoScDYUhyxemi5chlgnpWmObNo5dzVAVzjxo5gJeDIGpiyDqHvr6LBkprqb6XHcZhMWqIcdIHg== +"@angular-devkit/build-optimizer@0.803.21": + version "0.803.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.803.21.tgz#ecb3b6bba4b13ffbfbdbefb5997f690aa3635203" + integrity sha512-gNN6kPaF4phZco3TmsrNr9tIEKXYsoSeoaUiDUfgmCYwa7fAqM8Ojh7HX6IQuB2PpVmEwKGlCcSh6xDtB33NjA== dependencies: loader-utils "1.2.3" source-map "0.7.3" @@ -100,13 +100,13 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/build-webpack@0.803.20": - version "0.803.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.803.20.tgz#c03bd23a9f147c07201db681bf9fc3bfad95f9d9" - integrity sha512-35af8kD3KG/cIv7AB09YNER5HIPlx55ipBxdVk8D+X3MuUcTmD6fFvqXcV0EPlD1vQephthfzSgtNpvuPv4xuA== +"@angular-devkit/build-webpack@0.803.21": + version "0.803.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.803.21.tgz#fd45754c0123f44fcde8fa6411ebea52d98054f0" + integrity sha512-zCFVla/Xdk8qGVybvnHtoKml2h0/ShasSjT55VNZO1XaTCMqYkQEwwqSGEiVajpauafWjKrKxxBhsmWoI4efAA== dependencies: - "@angular-devkit/architect" "0.803.20" - "@angular-devkit/core" "8.3.20" + "@angular-devkit/architect" "0.803.21" + "@angular-devkit/core" "8.3.21" rxjs "6.4.0" "@angular-devkit/core@8.3.14": @@ -120,10 +120,10 @@ rxjs "6.4.0" source-map "0.7.3" -"@angular-devkit/core@8.3.20": - version "8.3.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.20.tgz#8a9e17e706905efab9875c16690e1d9328c9d5dd" - integrity sha512-UCfW/BJBJnioJU34QennQhA4o+rLoCXWiSrI2LM7yw8/MEM9I8KbqRETP1My3HjHkQnvP+Qh3noedpcu3Nnt8A== +"@angular-devkit/core@8.3.21": + version "8.3.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.21.tgz#447022813e46333e930816c287722d06b9c4dd3a" + integrity sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA== dependencies: ajv "6.10.2" fast-json-stable-stringify "2.0.0" @@ -139,12 +139,12 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/schematics@8.3.20": - version "8.3.20" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.20.tgz#80e7c31ebfd8f7f8500bfa1cae5c39980b962d6a" - integrity sha512-sDHZakh4e3A5WenR9zr1x6Va9GNRqQlRhqT3xcbkG88v2M0YqEt7dHB7YwnOhm7zSxiWQM8PdWEQHiQ4iu9NyQ== +"@angular-devkit/schematics@8.3.21": + version "8.3.21" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.21.tgz#80d515f480180be18a4130ea691f90153bcab3ea" + integrity sha512-+wH0362CRr/SijVX4w2baY2ANZ4scQ1k2xO8lT+NMeZQkw3IJQPOfwk1IaqiAs2xuBJZcSDH1Gn80+Jh4Dit7w== dependencies: - "@angular-devkit/core" "8.3.20" + "@angular-devkit/core" "8.3.21" rxjs "6.4.0" "@angular-eslint/builder@0.0.1-alpha.17": @@ -168,16 +168,16 @@ optionalDependencies: parse5 "^5.0.0" -"@angular/cli@8.3.20": - version "8.3.20" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-8.3.20.tgz#63e8f626e7dcf37e73cda820ab38bcac13423326" - integrity sha512-bCo8zVFZ6iPc1EnHmVCmKvIcV7YkvalBKGNU7LtVHq6qZBI+ZmFtuyL5obKvFg1vJcminjKcY/UcMr9uGcAQrQ== +"@angular/cli@8.3.21": + version "8.3.21" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-8.3.21.tgz#cbb05b86b7f34ecd81d52ccad922359e66a16a15" + integrity sha512-ZZpA7mMfIobFT06rBNxm8vucAh8W2s0huJZ4iL0BPujnhIr71PL+gDwssySWDEz2q6i4CkH9QRH76DHhtL6VSQ== dependencies: - "@angular-devkit/architect" "0.803.20" - "@angular-devkit/core" "8.3.20" - "@angular-devkit/schematics" "8.3.20" - "@schematics/angular" "8.3.20" - "@schematics/update" "0.803.20" + "@angular-devkit/architect" "0.803.21" + "@angular-devkit/core" "8.3.21" + "@angular-devkit/schematics" "8.3.21" + "@schematics/angular" "8.3.21" + "@schematics/update" "0.803.21" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "^4.1.1" @@ -278,7 +278,27 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@7.5.5", "@babel/core@>=7.2.2", "@babel/core@^7.0.1", "@babel/core@^7.1.0": +"@babel/core@7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e" + integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.4" + "@babel/helpers" "^7.7.4" + "@babel/parser" "^7.7.5" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@>=7.2.2", "@babel/core@^7.0.1", "@babel/core@^7.1.0": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== @@ -309,6 +329,16 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.7.4": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" + integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== + dependencies: + "@babel/types" "^7.7.4" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -316,6 +346,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-annotate-as-pure@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" + integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" @@ -324,6 +361,14 @@ "@babel/helper-explode-assignable-expression" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" + integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-call-delegate@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" @@ -333,6 +378,23 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/helper-call-delegate@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801" + integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA== + dependencies: + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-create-regexp-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" + integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A== + dependencies: + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/helper-define-map@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" @@ -342,6 +404,15 @@ "@babel/types" "^7.5.5" lodash "^4.17.13" +"@babel/helper-define-map@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" + integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" + "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" @@ -350,6 +421,14 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-explode-assignable-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" + integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg== + dependencies: + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-function-name@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" @@ -359,6 +438,15 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" + integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== + dependencies: + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -366,6 +454,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-get-function-arity@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" + integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -373,6 +468,13 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-hoist-variables@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" + integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-member-expression-to-functions@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" @@ -380,6 +482,13 @@ dependencies: "@babel/types" "^7.5.5" +"@babel/helper-member-expression-to-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" + integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -387,6 +496,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-module-imports@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" + integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" @@ -399,6 +515,18 @@ "@babel/types" "^7.5.5" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" + integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-simple-access" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" + "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" @@ -406,6 +534,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-optimise-call-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" + integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" @@ -429,6 +564,17 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-remap-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" + integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-wrap-function" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-replace-supers@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" @@ -439,6 +585,16 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" +"@babel/helper-replace-supers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" + integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" @@ -447,6 +603,14 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-simple-access@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" + integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A== + dependencies: + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" @@ -454,6 +618,13 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-split-export-declaration@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" + integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== + dependencies: + "@babel/types" "^7.7.4" + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -464,6 +635,16 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" +"@babel/helper-wrap-function@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" + integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/helpers@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" @@ -473,6 +654,15 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" +"@babel/helpers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" + integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== + dependencies: + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/highlight@^7.0.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" @@ -487,6 +677,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.7.4", "@babel/parser@^7.7.5": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" + integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -496,6 +691,15 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" +"@babel/plugin-proposal-async-generator-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" + integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" + "@babel/plugin-syntax-async-generators" "^7.7.4" + "@babel/plugin-proposal-dynamic-import@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" @@ -504,6 +708,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-dynamic-import" "^7.2.0" +"@babel/plugin-proposal-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" + integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + "@babel/plugin-proposal-json-strings@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" @@ -512,6 +724,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.2.0" +"@babel/plugin-proposal-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" + integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.7.4" + "@babel/plugin-proposal-object-rest-spread@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" @@ -520,6 +740,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" +"@babel/plugin-proposal-object-rest-spread@^7.7.4": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" + integrity sha512-3qp9I8lelgzNedI3hrhkvhaEYree6+WHnyA/q4Dza9z7iEIs1eyhWyJnetk3jJ69RT0AT4G0UhEGwyGFJ7GUuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" + "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" @@ -528,6 +756,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" +"@babel/plugin-proposal-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" + integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" + "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" @@ -537,6 +773,14 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-proposal-unicode-property-regex@^7.7.4": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.7.tgz#433fa9dac64f953c12578b29633f456b68831c4e" + integrity sha512-80PbkKyORBUVm1fbTLrHpYdJxMThzM1UqFGh0ALEhO9TYbG86Ah9zQYAB/84axz2vcxefDLdZwWwZNlYARlu9w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" @@ -544,6 +788,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-async-generators@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889" + integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" @@ -551,6 +802,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" + integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" @@ -558,6 +816,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" + integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" @@ -565,6 +830,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-object-rest-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" + integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" @@ -572,6 +844,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" + integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-top-level-await@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" + integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" @@ -579,6 +865,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-arrow-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" + integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-async-to-generator@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" @@ -588,6 +881,15 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" +"@babel/plugin-transform-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" + integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" + "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" @@ -595,6 +897,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-block-scoped-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" + integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-block-scoping@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz#a35f395e5402822f10d2119f6f8e045e3639a2ce" @@ -603,6 +912,14 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" +"@babel/plugin-transform-block-scoping@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" + integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + "@babel/plugin-transform-classes@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" @@ -617,6 +934,20 @@ "@babel/helper-split-export-declaration" "^7.4.4" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" + integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-define-map" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" @@ -624,6 +955,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-computed-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" + integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-destructuring@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" @@ -631,6 +969,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-destructuring@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" + integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" @@ -640,6 +985,14 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-transform-dotall-regex@^7.7.4": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.7.tgz#3e9713f1b69f339e87fa796b097d73ded16b937b" + integrity sha512-b4in+YlTeE/QmTgrllnb3bHA0HntYvjz8O3Mcbx75UBPJA2xhb5A8nle498VhxSXJHQefjtQxpnLPehDJ4TRlg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-duplicate-keys@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" @@ -647,6 +1000,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-duplicate-keys@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91" + integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-exponentiation-operator@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" @@ -655,6 +1015,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-exponentiation-operator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" + integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-for-of@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" @@ -662,6 +1030,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-for-of@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" + integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-function-name@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" @@ -670,6 +1045,14 @@ "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" + integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" @@ -677,6 +1060,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" + integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-member-expression-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" @@ -684,6 +1074,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-member-expression-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" + integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-modules-amd@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" @@ -693,6 +1090,15 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-amd@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" + integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ== + dependencies: + "@babel/helper-module-transforms" "^7.7.5" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-commonjs@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" @@ -703,6 +1109,16 @@ "@babel/helper-simple-access" "^7.1.0" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-commonjs@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" + integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== + dependencies: + "@babel/helper-module-transforms" "^7.7.5" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.7.4" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-systemjs@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" @@ -712,6 +1128,15 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-systemjs@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" + integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw== + dependencies: + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + "@babel/plugin-transform-modules-umd@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" @@ -720,6 +1145,14 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-modules-umd@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" + integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw== + dependencies: + "@babel/helper-module-transforms" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" @@ -727,6 +1160,13 @@ dependencies: regexp-tree "^0.1.6" +"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" + integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" @@ -734,6 +1174,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-new-target@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" + integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-object-super@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" @@ -742,6 +1189,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.5.5" +"@babel/plugin-transform-object-super@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" + integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/plugin-transform-parameters@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" @@ -751,6 +1206,15 @@ "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-parameters@^7.7.4": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" + integrity sha512-OhGSrf9ZBrr1fw84oFXj5hgi8Nmg+E2w5L7NhnG0lPvpDtqd7dbyilM2/vR8CKbJ907RyxPh2kj6sBCSSfI9Ew== + dependencies: + "@babel/helper-call-delegate" "^7.7.4" + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-property-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" @@ -758,6 +1222,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-property-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" + integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-regenerator@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" @@ -765,6 +1236,13 @@ dependencies: regenerator-transform "^0.14.0" +"@babel/plugin-transform-regenerator@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" + integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw== + dependencies: + regenerator-transform "^0.14.0" + "@babel/plugin-transform-reserved-words@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" @@ -772,6 +1250,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-reserved-words@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" + integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" @@ -779,6 +1264,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-shorthand-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" + integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-spread@^7.2.0": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" @@ -786,6 +1278,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" + integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" @@ -794,6 +1293,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" +"@babel/plugin-transform-sticky-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" + integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + "@babel/plugin-transform-template-literals@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" @@ -802,6 +1309,14 @@ "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-template-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" + integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-typeof-symbol@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" @@ -809,6 +1324,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-typeof-symbol@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" + integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-unicode-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" @@ -818,7 +1340,72 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/preset-env@7.5.5", "@babel/preset-env@^7.0.0": +"@babel/plugin-transform-unicode-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" + integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/preset-env@7.7.6": + version "7.7.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.6.tgz#39ac600427bbb94eec6b27953f1dfa1d64d457b2" + integrity sha512-k5hO17iF/Q7tR9Jv8PdNBZWYW6RofxhnxKjBMc0nG4JTaWvOTiPoO/RLFwAKcA4FpmuBFm6jkoqaRJLGi0zdaQ== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.7.4" + "@babel/plugin-proposal-dynamic-import" "^7.7.4" + "@babel/plugin-proposal-json-strings" "^7.7.4" + "@babel/plugin-proposal-object-rest-spread" "^7.7.4" + "@babel/plugin-proposal-optional-catch-binding" "^7.7.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.7.4" + "@babel/plugin-syntax-async-generators" "^7.7.4" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + "@babel/plugin-syntax-json-strings" "^7.7.4" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" + "@babel/plugin-syntax-top-level-await" "^7.7.4" + "@babel/plugin-transform-arrow-functions" "^7.7.4" + "@babel/plugin-transform-async-to-generator" "^7.7.4" + "@babel/plugin-transform-block-scoped-functions" "^7.7.4" + "@babel/plugin-transform-block-scoping" "^7.7.4" + "@babel/plugin-transform-classes" "^7.7.4" + "@babel/plugin-transform-computed-properties" "^7.7.4" + "@babel/plugin-transform-destructuring" "^7.7.4" + "@babel/plugin-transform-dotall-regex" "^7.7.4" + "@babel/plugin-transform-duplicate-keys" "^7.7.4" + "@babel/plugin-transform-exponentiation-operator" "^7.7.4" + "@babel/plugin-transform-for-of" "^7.7.4" + "@babel/plugin-transform-function-name" "^7.7.4" + "@babel/plugin-transform-literals" "^7.7.4" + "@babel/plugin-transform-member-expression-literals" "^7.7.4" + "@babel/plugin-transform-modules-amd" "^7.7.5" + "@babel/plugin-transform-modules-commonjs" "^7.7.5" + "@babel/plugin-transform-modules-systemjs" "^7.7.4" + "@babel/plugin-transform-modules-umd" "^7.7.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.4" + "@babel/plugin-transform-new-target" "^7.7.4" + "@babel/plugin-transform-object-super" "^7.7.4" + "@babel/plugin-transform-parameters" "^7.7.4" + "@babel/plugin-transform-property-literals" "^7.7.4" + "@babel/plugin-transform-regenerator" "^7.7.5" + "@babel/plugin-transform-reserved-words" "^7.7.4" + "@babel/plugin-transform-shorthand-properties" "^7.7.4" + "@babel/plugin-transform-spread" "^7.7.4" + "@babel/plugin-transform-sticky-regex" "^7.7.4" + "@babel/plugin-transform-template-literals" "^7.7.4" + "@babel/plugin-transform-typeof-symbol" "^7.7.4" + "@babel/plugin-transform-unicode-regex" "^7.7.4" + "@babel/types" "^7.7.4" + browserslist "^4.6.0" + core-js-compat "^3.4.7" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/preset-env@^7.0.0": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" integrity sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A== @@ -890,6 +1477,15 @@ "@babel/parser" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/template@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" + integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" + "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" @@ -905,6 +1501,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" @@ -914,6 +1525,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babylonjs/core@4.1.0-beta.12": version "4.1.0-beta.12" resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.12.tgz#9aaaa51fa4fc72defb9e444d8376294f3bccbb0b" @@ -1172,12 +1792,12 @@ resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-8.6.0.tgz#8540c5bd40b33fc2f443e7e86f47c0d801b8f413" integrity sha512-K4cvCEa+5hw9qrETQWO+Cha3YbVCAT8yaIKJr/N35KntTL9mQMjoL+51JWLZfBwPV0e19CFgJIyrBnVUTxwr2A== -"@ngtools/webpack@8.3.20": - version "8.3.20" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-8.3.20.tgz#a5288171b67c96e8d3b219f5108f1d6cd962d6a3" - integrity sha512-2e9Kat6PQEzqtNsZZpnOIvoDzyGwMELiuBYBa9keZeaXOD6TxjSyCRzHHXAldAXqvh4Uj2qjTid54Sy14CxtsQ== +"@ngtools/webpack@8.3.21": + version "8.3.21" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-8.3.21.tgz#d28f2b66a8aeced5260c42ae722192ec5d5e4e56" + integrity sha512-DGqmFQ52sV4uB3y3spQTNLa69oU5cwd1yIqMB4GSM+Qp+hozdzrPA2gVH90N2DDhWe8icsSQHAtZQiR9+BDL8g== dependencies: - "@angular-devkit/core" "8.3.20" + "@angular-devkit/core" "8.3.21" enhanced-resolve "4.1.0" rxjs "6.4.0" tree-kill "1.2.1" @@ -1306,21 +1926,21 @@ "@angular-devkit/core" "8.3.14" "@angular-devkit/schematics" "8.3.14" -"@schematics/angular@8.3.20": - version "8.3.20" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-8.3.20.tgz#737d0a73e891446899a2267c4cc348b6c5a78ca8" - integrity sha512-Y20pSJhQ0KQd8Tk2kPQlmpRDNDaoIKMeOOGLT2FgCFrumxZXuIbBgN9fGDgW40iI2sq80bccOeo24RKkn3QpcA== +"@schematics/angular@8.3.21": + version "8.3.21" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-8.3.21.tgz#4902e0b6e8be47006859009bf96a026e3d39dd27" + integrity sha512-KahQ+dHvTsGOZwY6IdzqJZLDEn0G89rrK3OY+7okZujoaLM+LXhxlPoznW1udnZJVTa3VNxYGx11fkgLtRJRqA== dependencies: - "@angular-devkit/core" "8.3.20" - "@angular-devkit/schematics" "8.3.20" + "@angular-devkit/core" "8.3.21" + "@angular-devkit/schematics" "8.3.21" -"@schematics/update@0.803.20": - version "0.803.20" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.803.20.tgz#f6cce4f0ee435d8a4071817ac43e418f2b51d22a" - integrity sha512-MseLreuHdnSLUEnRxZFVSHKKK+3mGXH12SgOSeirwATIL22Df74+Q5BYvsge/Kd2k6s9ak/NCuRXG7FAo8mkMA== +"@schematics/update@0.803.21": + version "0.803.21" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.803.21.tgz#572c955bb132348bca03a128491ae264b0068a0a" + integrity sha512-D3BRvEBF2cJEgogvFaNOfqtTFHHv/ctSRfOeAYWjUxILtb+2DpuZ9h5QYDFhN9MPgz/vRaOqFORa3sEZCRkX4g== dependencies: - "@angular-devkit/core" "8.3.20" - "@angular-devkit/schematics" "8.3.20" + "@angular-devkit/core" "8.3.21" + "@angular-devkit/schematics" "8.3.21" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" pacote "9.5.5" @@ -2458,6 +3078,15 @@ browserslist@^4.7.3: electron-to-chromium "^1.3.306" node-releases "^1.1.40" +browserslist@^4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289" + integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA== + dependencies: + caniuse-lite "^1.0.30001015" + electron-to-chromium "^1.3.322" + node-releases "^1.1.42" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -2547,7 +3176,7 @@ cacache@12.0.2, cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^11.3.2, cacache@^11.3.3: +cacache@^11.3.2: version "11.3.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc" integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA== @@ -2567,7 +3196,7 @@ cacache@^11.3.2, cacache@^11.3.3: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^12.0.0: +cacache@^12.0.0, cacache@^12.0.3: version "12.0.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== @@ -2668,6 +3297,11 @@ caniuse-lite@^1.0.30001010: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001012.tgz#653ec635e815b9e0fb801890923b0c2079eb34ec" integrity sha512-7RR4Uh04t9K1uYRWzOJmzplgEOAXbfK72oVNokCdMzA67trrhPzy93ahKk1AWHiA0c58tD2P+NHqxrA8FZ+Trg== +caniuse-lite@^1.0.30001015: + version "1.0.30001016" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz#16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66" + integrity sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA== + canonical-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" @@ -3094,6 +3728,13 @@ convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, dependencies: safe-buffer "~5.1.1" +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -3139,12 +3780,12 @@ copy-webpack-plugin@5.0.3: serialize-javascript "^1.7.0" webpack-log "^2.0.0" -copy-webpack-plugin@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz#c78126f604e24f194c6ec2f43a64e232b5d43655" - integrity sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg== +copy-webpack-plugin@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" + integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== dependencies: - cacache "^11.3.3" + cacache "^12.0.3" find-cache-dir "^2.1.0" glob-parent "^3.1.0" globby "^7.1.1" @@ -3152,9 +3793,9 @@ copy-webpack-plugin@5.0.4: loader-utils "^1.2.3" minimatch "^3.0.4" normalize-path "^3.0.0" - p-limit "^2.2.0" + p-limit "^2.2.1" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" webpack-log "^2.0.0" core-js-compat@^3.1.1: @@ -3165,6 +3806,14 @@ core-js-compat@^3.1.1: browserslist "^4.6.6" semver "^6.3.0" +core-js-compat@^3.4.7: + version "3.6.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.0.tgz#4eb6cb69d03d99159ed7c860cd5fcf7d23a62ea9" + integrity sha512-Z3eCNjGgoYluH89Jt4wVkfYsc/VdLrA2/woX5lm0isO/pCT+P+Y+o65bOuEnjDJLthdwTBxbCVzptTXtc18fJg== + dependencies: + browserslist "^4.8.2" + semver "7.0.0" + core-js@3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" @@ -3728,6 +4377,11 @@ electron-to-chromium@^1.3.306: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.314.tgz#c186a499ed2c9057bce9eb8dca294d6d5450facc" integrity sha512-IKDR/xCxKFhPts7h+VaSXS02Z1mznP3fli1BbXWXeN89i2gCzKraU8qLpEid8YzKcmZdZD3Mly3cn5/lY9xsBQ== +electron-to-chromium@^1.3.322: + version "1.3.322" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" + integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -7065,6 +7719,13 @@ node-releases@^1.1.40: dependencies: semver "^6.3.0" +node-releases@^1.1.42: + version "1.1.43" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2" + integrity sha512-Rmfnj52WNhvr83MvuAWHEqXVoZXCcDQssSOffU4n4XOL9sPrP61mSZ88g25NqmABDvH7PiAlFCzoSCSdzA293w== + dependencies: + semver "^6.3.0" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -7445,6 +8106,13 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -8360,6 +9028,18 @@ regexpu-core@^4.5.4: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -8818,6 +9498,11 @@ semver@6.3.0, semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -8842,6 +9527,11 @@ serialize-javascript@^1.7.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -9649,7 +10339,22 @@ tar@^4, tar@^4.4.8: safe-buffer "^5.1.2" yallist "^3.0.3" -terser-webpack-plugin@1.4.1, terser-webpack-plugin@^1.4.1: +terser-webpack-plugin@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser-webpack-plugin@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== From 479c81b3edc3e1679c43154f1062165b9d63019f Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Wed, 8 Jan 2020 17:28:24 +0100 Subject: [PATCH 35/67] feat(frontend): draw separate mesh per InternalNode1 (#9) * feat(frontend): add multiple voxels * feat(ui): add output for dropped files * doc(readme): add openVDB repo link * feat(vdb): implement `beginLeafOn` iterator * feat(frontend/vdb): draw InternalNode1 chunks * feat(frontend/vdb): don't return LeafNode * feat(frontend/vdb): don't return `LeafNode` in `setValueAndCache` * feat(frontend/vdb): use only key from accessor * feat(frontend/vdb): remove `getLeafNodeAndCache` * feat(frontend/vdb): remove `beginLeafOn` * feat(frontend/vdb): remove `getLeafNodeAndCache` & `beginLeafOn` * fix(frontend/vdb): dispose mesh instead of just remove it: - so we resolve memory issue * refactor(frontend): optimize scene & mesh - https://doc.babylonjs.com/how_to/optimizing_your_scene * refactor(frontend): remove unused method & obj loader * refactor(vdb): increase `InternalNode1` size to reduce draw calls * refactor(vdb): remove inspector & loading obj * refactor(vdb): align to `probeNode` & `probeNodeAndCache` * refactor(vdb): s/grid-to-mesh/node-to-mesh * refactor(vdb): use un-indexed mesh * fix(ui): read normal directly from picked mesh * refactor(frontend): remove `objFileLoader` * refactor(frontend): s/updateGridMesh/updateNodeMesh & key/Node1Origin --- .../scene-viewer-container/grid.service.ts | 41 +- .../scene-viewer-container.actions.ts | 20 +- .../scene-viewer-container.effects.ts | 46 +- .../scene-viewer/scene-viewer.component.ts | 57 ++- .../lib/scene-viewer/scene-viewer.service.ts | 72 ++- libs/vdb/README.md | 1 + libs/vdb/src/lib/math/coord.ts | 8 + libs/vdb/src/lib/tools/grid-to-mesh.spec.ts | 26 - libs/vdb/src/lib/tools/grid-to-mesh.ts | 84 ---- libs/vdb/src/lib/tools/index.ts | 2 +- libs/vdb/src/lib/tools/node-to-mesh.spec.ts | 26 + libs/vdb/src/lib/tools/node-to-mesh.ts | 451 ++++++++++++++++++ libs/vdb/src/lib/tree/index.ts | 1 + libs/vdb/src/lib/tree/internal-node.spec.ts | 87 ++-- libs/vdb/src/lib/tree/internal-node.ts | 21 +- libs/vdb/src/lib/tree/leaf-node.ts | 10 +- libs/vdb/src/lib/tree/node.ts | 8 + libs/vdb/src/lib/tree/root-node.ts | 20 +- libs/vdb/src/lib/tree/value-accessor.ts | 22 +- 19 files changed, 803 insertions(+), 200 deletions(-) delete mode 100644 libs/vdb/src/lib/tools/grid-to-mesh.spec.ts delete mode 100644 libs/vdb/src/lib/tools/grid-to-mesh.ts create mode 100644 libs/vdb/src/lib/tools/node-to-mesh.spec.ts create mode 100644 libs/vdb/src/lib/tools/node-to-mesh.ts diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index 4b2d47c9..9197d9e7 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Coord, Grid, gridToMesh, MeshData } from '@talus/vdb'; +import { Coord, Grid, MeshData, nodeToMesh } from '@talus/vdb'; /** * Keeps the mutable state of the single grid. This state is not part of the store, due to @@ -12,15 +12,46 @@ export class GridService { grid = new Grid(0); accessor = this.grid.getAccessor(); - addVoxel(xyz: Coord, value: number): void { + /** + * Adds a new voxel via accessor to share access path. + * @returns origin of `InternalNode1` of affected node (node containing added voxel). + */ + addVoxel(xyz: Coord, value: number): Coord { this.accessor.setValue(xyz, value); + + return this.accessor.internalNode1Origin; + } + + addVoxels(coords: Coord[], values: number[]): Coord[] { + const affectedOrigins = new Map(); + + if (coords.length !== values.length) { + coords.forEach(xyz => { + const affected = this.addVoxel(xyz, values[0]); + affectedOrigins.set(affected.toString(), affected); + }); + } else { + coords.forEach((xyz, i) => { + const affected = this.addVoxel(xyz, values[i]); + affectedOrigins.set(affected.toString(), affected); + }); + } + + return Array.from(affectedOrigins.values()); } - removeVoxel(xyz: Coord): void { + removeVoxel(xyz: Coord): Coord { this.accessor.setValueOff(xyz, this.grid.background); + + return this.accessor.internalNode1Origin; } - computeMesh(): MeshData | undefined { - return gridToMesh(this.grid); + computeInternalNode1Mesh(origin: Coord): MeshData | undefined { + const internal1 = this.accessor.probeInternalNode1(origin); + + const mesh = nodeToMesh(internal1); + mesh.origin = internal1.origin; + + return mesh; } } diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts index d8f32abc..1651f716 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -8,11 +8,27 @@ export const addVoxel = createAction( props<{ position: Coord; value: number }>(), ); export const addVoxelFailed = createAction(`${actionTypePrefix} Add voxel failed`); -export const voxelAdded = createAction(`${actionTypePrefix} Voxel added`); +export const voxelAdded = createAction( + `${actionTypePrefix} Voxel added`, + props<{ affectedOrigins: Coord[] }>(), +); + +export const addVoxels = createAction( + `${actionTypePrefix} Add voxels`, + props<{ positions: Coord[]; values: number[] }>(), +); +export const addVoxelsFailed = createAction(`${actionTypePrefix} Add voxels failed`); +export const voxelsAdded = createAction( + `${actionTypePrefix} Voxels added`, + props<{ affectedOrigins: Coord[] }>(), +); export const removeVoxel = createAction( `${actionTypePrefix} Remove voxel`, props<{ position: Coord }>(), ); export const removeVoxelFailed = createAction(`${actionTypePrefix} Remove voxel failed`); -export const voxelRemoved = createAction(`${actionTypePrefix} Voxel removed`); +export const voxelRemoved = createAction( + `${actionTypePrefix} Voxel removed`, + props<{ affectedOrigins: Coord[] }>(), +); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts index 20571c6c..fda8cc88 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts @@ -7,10 +7,13 @@ import { GridService } from './grid.service'; import { addVoxel, addVoxelFailed, + addVoxels, + addVoxelsFailed, removeVoxel, removeVoxelFailed, voxelAdded, voxelRemoved, + voxelsAdded, } from './scene-viewer-container.actions'; @Injectable() @@ -24,28 +27,43 @@ export class SceneViewerContainerEffects { addVoxel$ = createEffect(() => this.actions$.pipe( ofType(addVoxel), - tap({ - next: ({ position, value }) => { - this.gridService.addVoxel(position, value); - this.sceneViewerService.updateGridMesh(this.gridService.computeMesh()); - }, - }), - map(() => voxelAdded()), + map(({ position, value }) => this.gridService.addVoxel(position, value)), + map(affectedOrigin => voxelAdded({ affectedOrigins: [affectedOrigin] })), catchError(() => of(addVoxelFailed())), ), ); + addVoxels$ = createEffect(() => + this.actions$.pipe( + ofType(addVoxels), + map(({ positions, values }) => this.gridService.addVoxels(positions, values)), + map(affectedOrigins => voxelsAdded({ affectedOrigins })), + catchError(() => of(addVoxelsFailed())), + ), + ); + removeVoxel$ = createEffect(() => this.actions$.pipe( ofType(removeVoxel), - tap({ - next: ({ position }) => { - this.gridService.removeVoxel(position); - this.sceneViewerService.updateGridMesh(this.gridService.computeMesh()); - }, - }), - map(() => voxelRemoved()), + map(({ position }) => this.gridService.removeVoxel(position)), + map(affectedOrigin => voxelRemoved({ affectedOrigins: [affectedOrigin] })), catchError(() => of(removeVoxelFailed())), ), ); + + updateGridMesh$ = createEffect( + () => + this.actions$.pipe( + ofType(voxelAdded, voxelsAdded, voxelRemoved), + tap({ + next: ({ affectedOrigins }) => { + affectedOrigins.map(origin => { + const mesh = this.gridService.computeInternalNode1Mesh(origin); + this.sceneViewerService.updateNodeMesh(mesh); + }); + }, + }), + ), + { dispatch: false }, + ); } diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts index 6c5538ae..5d363801 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts @@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, ElementRef, + EventEmitter, HostListener, OnInit, Output, @@ -12,25 +13,71 @@ import { SceneViewerService } from './scene-viewer.service'; @Component({ selector: 'ui-scene-viewer', template: ` - + `, styleUrls: ['./scene-viewer.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerComponent implements OnInit { + constructor(private sceneViewerService: SceneViewerService) {} + @ViewChild('canvas', { static: true }) canvas: ElementRef; @Output() pointerPick = this.sceneViewerService.pointerPick$; - constructor(private sceneViewerService: SceneViewerService) {} + @Output() dropFiles = new EventEmitter(); + + ngOnInit(): void { + this.sceneViewerService.initialize(this.canvas.nativeElement); + this.sceneViewerService.startRendering(); + } @HostListener('window:resize') onWindowsResize(): void { this.sceneViewerService.resizeView(); } - ngOnInit(): void { - this.sceneViewerService.initialize(this.canvas.nativeElement); - this.sceneViewerService.startRendering(); + onDragOver(event: DragEvent): void { + // Prevent file from being opened + event.preventDefault(); + } + + onDrop(event: DragEvent): void { + // Prevent file from being opened + event.preventDefault(); + + this.dropFiles.emit(this.getFiles(event)); + } + + // Source: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop + private getFiles(event: DragEvent): File[] { + return event.dataTransfer.items + ? this.getFilesFromDataTransferItemList(event) + : this.getFilesFromDataTransfer(event); + } + + private getFilesFromDataTransferItemList(event: DragEvent): File[] { + const files: File[] = []; + + // Use DataTransferItemList interface to access the file(s) + for (let i = 0; i < event.dataTransfer.items.length; i++) { + // If dropped items aren't files, reject them + if (event.dataTransfer.items[i].kind === 'file') { + files.push(event.dataTransfer.items[i].getAsFile()); + } + } + + return files; + } + + private getFilesFromDataTransfer(event: DragEvent): File[] { + const files: File[] = []; + + // Use DataTransfer interface to access the file(s) + for (let i = 0; i < event.dataTransfer.files.length; i++) { + files.push(event.dataTransfer.files[i]); + } + + return files; } } diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 1ffeb152..cc507dec 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -7,9 +7,11 @@ import { Engine } from '@babylonjs/core/Engines/engine'; import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight'; import '@babylonjs/core/Materials/standardMaterial'; import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import { VertexBuffer } from '@babylonjs/core/Meshes/buffer'; import { Mesh } from '@babylonjs/core/Meshes/mesh'; import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData'; import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder'; +import { TransformNode } from '@babylonjs/core/Meshes/transformNode'; import '@babylonjs/core/Physics/physicsHelper'; // Needed for `onPointerPick` import { Scene } from '@babylonjs/core/scene'; import { Coord, MeshData } from '@talus/vdb'; @@ -52,12 +54,11 @@ export class CameraFactory { */ @Injectable() export class SceneViewerService { - scene: Scene; - gridMesh: Mesh; - pointerPick$ = new Subject(); private engine: Engine; + private scene: Scene; + private gridNode: TransformNode; // @ts-ignore: noUnusedLocals private light: HemisphericLight; @@ -65,8 +66,7 @@ export class SceneViewerService { initialize(canvas: HTMLCanvasElement): void { this.engine = this.engineFactory.create(canvas); - this.scene = new Scene(this.engine); - + this.createScene(); this.createCamera(); this.createLight(); @@ -86,22 +86,43 @@ export class SceneViewerService { this.engine.resize(); } - updateGridMesh(mesh?: MeshData): void { - this.scene.removeMesh(this.gridMesh); + updateNodeMesh(mesh?: MeshData): void { + const meshName = `node1 [${mesh.origin}]`; + + this.deleteMesh(meshName); if (mesh) { - this.gridMesh = new Mesh('grid', this.scene); const data = new VertexData(); + const nodeMesh = new Mesh(meshName, this.scene, this.gridNode); + // https://www.html5gamedevs.com/topic/31617-mesh-without-indices/?tab=comments#comment-181659 + // https://doc.babylonjs.com/how_to/optimizing_your_scene#using-unindexed-meshes + nodeMesh._unIndexed = true; data.colors = mesh.colors; - data.indices = mesh.indices; + data.normals = mesh.normals; data.positions = mesh.positions; - data.applyToMesh(this.gridMesh); - this.gridMesh.convertToFlatShadedMesh(); + data.applyToMesh(nodeMesh); + + // https://doc.babylonjs.com/how_to/optimizing_your_scene + // https://www.html5gamedevs.com/topic/12504-performancedraw-calls/ + nodeMesh.freezeNormals(); + nodeMesh.freezeWorldMatrix(); } } + private createScene(): void { + // https://doc.babylonjs.com/how_to/optimizing_your_scene + this.scene = new Scene(this.engine, { + useGeometryUniqueIdsMap: true, + useClonedMeshhMap: true, + }); + this.scene.freezeMaterials(); + + // Used only as parent to have all nodes grouped together + this.gridNode = new TransformNode('grid', this.scene); + } + private createCamera(): void { const camera: ArcRotateCamera = this.cameraFactory.create( 'camera', @@ -113,8 +134,9 @@ export class SceneViewerService { ); camera.inertia = 0; camera.panningInertia = 0; + camera.wheelPrecision = 1.0; - camera.panningSensibility = 20; + camera.panningSensibility = 10; camera.angularSensibilityX = 200; camera.angularSensibilityY = 100; @@ -131,12 +153,36 @@ export class SceneViewerService { const info: PointerPickInfo = { pickedPoint: vector3ToCoord(pickInfo.pickedPoint), pointerButton: event.button, - normal: vector3ToCoord(pickInfo.getNormal()), + normal: this.getNormal(pickInfo), }; this.pointerPick$.next(info); }; } + + /** + * PickingInfo.getNormal() requires to have indices which are not available + * for an unindexed custom mesh. Therefore, read normals directly from picked mesh. + * + * https://github.com/BabylonJS/Babylon.js/blob/master/src/Collisions/pickingInfo.ts#L65 + */ + private getNormal(pickInfo: PickingInfo): Coord { + const normals = pickInfo.pickedMesh.getVerticesData(VertexBuffer.NormalKind); + + return [ + normals[pickInfo.faceId * 9], + normals[pickInfo.faceId * 9 + 1], + normals[pickInfo.faceId * 9 + 2], + ]; + } + + private deleteMesh(name: string): void { + const oldMesh = this.scene.getMeshByName(name); + + if (oldMesh) { + oldMesh.dispose(); + } + } } function vector3ToCoord(vector: Vector3): Coord { diff --git a/libs/vdb/README.md b/libs/vdb/README.md index bc063f73..76cc2814 100644 --- a/libs/vdb/README.md +++ b/libs/vdb/README.md @@ -17,6 +17,7 @@ When manipulating data in OpenVDB, the three essential objects are ### Sources +- [Repo](https://github.com/AcademySoftwareFoundation/openvdb) - [Overview](https://www.openvdb.org/documentation/doxygen/overview.html) - [Cookbook](https://www.openvdb.org/documentation/doxygen/codeExamples.html) diff --git a/libs/vdb/src/lib/math/coord.ts b/libs/vdb/src/lib/math/coord.ts index 0001351f..f0ec4069 100644 --- a/libs/vdb/src/lib/math/coord.ts +++ b/libs/vdb/src/lib/math/coord.ts @@ -24,3 +24,11 @@ export function createMaxCoord(): Coord { export function createMinCoord(): Coord { return [Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE]; } + +export function areEqual(c1: Coord, c2: Coord): boolean { + return c1[0] === c2[0] && c1[1] === c2[1] && c1[2] === c2[2]; +} + +export function clone(c: Coord): Coord { + return [c[0], c[1], c[2]]; +} diff --git a/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts b/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts deleted file mode 100644 index ab6a602f..00000000 --- a/libs/vdb/src/lib/tools/grid-to-mesh.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Grid } from '../grid'; -import { gridToMesh } from './grid-to-mesh'; - -describe('gridToMesh()', () => { - it('should generate the mesh', () => { - const grid = new Grid(0); - const accessor = grid.getAccessor(); - - accessor.setValue([0, 0, 0], 1); - accessor.setValue([0, 0, 1], 1); - - const meshData = gridToMesh(grid); - - const voxels = 2; - - const corners = 8; - const triangles = 12; - - const xyz = 3; - const rgba = 4; - - expect(meshData.positions.length).toEqual(voxels * corners * xyz); - expect(meshData.colors.length).toEqual(voxels * corners * rgba); - expect(meshData.indices.length).toEqual(voxels * triangles * xyz); - }); -}); diff --git a/libs/vdb/src/lib/tools/grid-to-mesh.ts b/libs/vdb/src/lib/tools/grid-to-mesh.ts deleted file mode 100644 index fe5218ec..00000000 --- a/libs/vdb/src/lib/tools/grid-to-mesh.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Babylon.js has a left-handed coordinate system with Y pointing up. - * Furthermore, the front face of a facet is considered the face where the facet’s vertices - * are positioned counterclockwise. - * - * Position of a facet is the location of the facet’s barycenter (a.k.a. centroid). - * - * 6-------7 - * /| /| - * / | / | - * Y 3--|----2 | - * | Z | 5----|--4 - * | / | / | / - * 0--- X 0-------1 - */ - -import { Grid } from '../grid'; - -export interface MeshData { - colors: number[]; - indices: number[]; - // normals: number[]; - positions: number[]; -} - -/** - * Returns a mesh if there are any active voxels saved in the grid. - * Otherwise, returns `undefined` i.e. if there are no active voxels. - */ -export function gridToMesh(grid: Grid): MeshData | undefined { - const mesh: MeshData = { - colors: [], - indices: [], - positions: [], - // normals: [], - }; - - let vertexCount = 0; - for (const voxel of grid.beginVoxelOn()) { - const [x, y, z] = voxel.globalCoord; - - mesh.indices.push(...[5, 0, 3, 3, 6, 5].map(i => i + vertexCount)); // Left - mesh.indices.push(...[1, 4, 7, 7, 2, 1].map(i => i + vertexCount)); // Right - - mesh.indices.push(...[5, 4, 1, 1, 0, 5].map(i => i + vertexCount)); // Bottom - mesh.indices.push(...[7, 6, 3, 3, 2, 7].map(i => i + vertexCount)); // Top - - mesh.indices.push(...[0, 1, 2, 2, 3, 0].map(i => i + vertexCount)); // Front - mesh.indices.push(...[4, 5, 6, 6, 7, 4].map(i => i + vertexCount)); // Back - - // mesh.normals.push(-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0); // Left - // mesh.normals.push(1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0); // Right - - // mesh.normals.push(0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0); // Bottom - // mesh.normals.push(0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0); // Top - - // mesh.normals.push(0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1); // Front - // mesh.normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1); // Back - - mesh.positions.push(x, y, z); // 0 - mesh.positions.push(x + 1, y, z); // 1 - mesh.positions.push(x + 1, y + 1, z); // 2 - mesh.positions.push(x, y + 1, z); // 3 - - mesh.positions.push(x + 1, y, z + 1); // 4 - mesh.positions.push(x, y, z + 1); // 5 - mesh.positions.push(x, y + 1, z + 1); // 6 - mesh.positions.push(x + 1, y + 1, z + 1); // 7 - - vertexCount += 8; - - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - mesh.colors.push(0, 1, 0, 1); - } - - return vertexCount !== 0 ? mesh : undefined; -} diff --git a/libs/vdb/src/lib/tools/index.ts b/libs/vdb/src/lib/tools/index.ts index e2f1c696..479b8e5c 100644 --- a/libs/vdb/src/lib/tools/index.ts +++ b/libs/vdb/src/lib/tools/index.ts @@ -1 +1 @@ -export * from './grid-to-mesh'; +export * from './node-to-mesh'; diff --git a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts new file mode 100644 index 00000000..60cdd34e --- /dev/null +++ b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts @@ -0,0 +1,26 @@ +import { Grid } from '../grid'; +import { nodeToMesh } from './node-to-mesh'; + +describe('nodeToMesh()', () => { + it('should generate the mesh', () => { + const grid = new Grid(0); + const accessor = grid.getAccessor(); + + accessor.setValue([0, 0, 0], 1); + accessor.setValue([0, 0, 1], 1); + + const meshData = nodeToMesh(grid.tree.root); + + const voxels = 2; + + const triangles = 12; + const triangleCorners = triangles * 3; + + const xyz = 3; + const rgba = 4; + + expect(meshData.positions.length).toEqual(voxels * triangleCorners * xyz); + expect(meshData.colors.length).toEqual(voxels * triangleCorners * rgba); + expect(meshData.normals.length).toEqual(meshData.positions.length); + }); +}); diff --git a/libs/vdb/src/lib/tools/node-to-mesh.ts b/libs/vdb/src/lib/tools/node-to-mesh.ts new file mode 100644 index 00000000..f3d73b8f --- /dev/null +++ b/libs/vdb/src/lib/tools/node-to-mesh.ts @@ -0,0 +1,451 @@ +/** + * Babylon.js has a left-handed coordinate system with Y pointing up. + * Furthermore, the front face of a facet is considered the face where the facet’s vertices + * are positioned counterclockwise. + * + * Position of a facet is the location of the facet’s barycenter (a.k.a. centroid). + * + * 6-------7 + * /| /| + * / | / | + * Y 3--|----2 | + * | Z | 5----|--4 + * | / | / | / + * 0--- X 0-------1 + */ + +import { Coord } from '../math'; +import { HashableNode } from '../tree/node'; + +export interface MeshData { + colors: number[]; + normals: number[]; + origin?: Coord; + positions: number[]; +} + +/** + * Returns a mesh if there are any active voxels saved in the grid. + * Otherwise, returns `undefined` i.e. if there are no active voxels. + * + * Doesn't use indices, since it is more efficient to send 32 positions + * instead of 24 positions and 32 indices for a cube. + * See: https://doc.babylonjs.com/how_to/optimizing_your_scene#using-unindexed-meshes + */ +export function nodeToMesh(node: HashableNode): MeshData | undefined { + const mesh: MeshData = { + colors: [], + positions: [], + normals: [], + }; + + const r = Math.random(); + const g = Math.random(); + const b = Math.random(); + + for (const voxel of node.beginVoxelOn()) { + const [x, y, z] = voxel.globalCoord; + + const v0 = [x, y, z]; + const v1 = [x + 1, y, z]; + const v2 = [x + 1, y + 1, z]; + const v3 = [x, y + 1, z]; + const v4 = [x + 1, y, z + 1]; + const v5 = [x, y, z + 1]; + const v6 = [x, y + 1, z + 1]; + const v7 = [x + 1, y + 1, z + 1]; + + mesh.positions.push( + // Front + v4[0], + v4[1], + v4[2], + v5[0], + v5[1], + v5[2], + v6[0], + v6[1], + v6[2], + v4[0], + v4[1], + v4[2], + v6[0], + v6[1], + v6[2], + v7[0], + v7[1], + v7[2], + + // Back + v0[0], + v0[1], + v0[2], + v1[0], + v1[1], + v1[2], + v2[0], + v2[1], + v2[2], + v0[0], + v0[1], + v0[2], + v2[0], + v2[1], + v2[2], + v3[0], + v3[1], + v3[2], + + // Left + v5[0], + v5[1], + v5[2], + v0[0], + v0[1], + v0[2], + v3[0], + v3[1], + v3[2], + v5[0], + v5[1], + v5[2], + v3[0], + v3[1], + v3[2], + v6[0], + v6[1], + v6[2], + + // Right + v1[0], + v1[1], + v1[2], + v4[0], + v4[1], + v4[2], + v7[0], + v7[1], + v7[2], + v1[0], + v1[1], + v1[2], + v7[0], + v7[1], + v7[2], + v2[0], + v2[1], + v2[2], + + // Top + v3[0], + v3[1], + v3[2], + v2[0], + v2[1], + v2[2], + v7[0], + v7[1], + v7[2], + v3[0], + v3[1], + v3[2], + v7[0], + v7[1], + v7[2], + v6[0], + v6[1], + v6[2], + + // Bottom + v5[0], + v5[1], + v5[2], + v4[0], + v4[1], + v4[2], + v1[0], + v1[1], + v1[2], + v5[0], + v5[1], + v5[2], + v1[0], + v1[1], + v1[2], + v0[0], + v0[1], + v0[2], + ); + + // Front + mesh.normals.push( + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + + // Back + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + + // Left + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + + // Right + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + + // Top + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + + // Bottom + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + ); + + mesh.colors.push( + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + r, + g, + b, + 1, + ); + } + + return mesh.positions.length !== 0 ? mesh : undefined; +} diff --git a/libs/vdb/src/lib/tree/index.ts b/libs/vdb/src/lib/tree/index.ts index 54c0aae2..6ed61bee 100644 --- a/libs/vdb/src/lib/tree/index.ts +++ b/libs/vdb/src/lib/tree/index.ts @@ -1 +1,2 @@ +export * from './leaf-node'; export * from './internal-node'; diff --git a/libs/vdb/src/lib/tree/internal-node.spec.ts b/libs/vdb/src/lib/tree/internal-node.spec.ts index b8b51738..8307d50e 100644 --- a/libs/vdb/src/lib/tree/internal-node.spec.ts +++ b/libs/vdb/src/lib/tree/internal-node.spec.ts @@ -5,12 +5,12 @@ import { LeafNode } from './leaf-node'; describe('InternalNode', () => { describe('InternalNode1', () => { describe('static config values', () => { - expect(InternalNode1.LOG2DIM).toEqual(2); - expect(InternalNode1.TOTAL).toEqual(5); - expect(InternalNode1.DIM).toEqual(32); - expect(InternalNode1.NUM_VALUES).toEqual(64); + expect(InternalNode1.LOG2DIM).toEqual(3); + expect(InternalNode1.TOTAL).toEqual(3 + 3); + expect(InternalNode1.DIM).toEqual(64); + expect(InternalNode1.NUM_VALUES).toEqual(512); expect(InternalNode1.LEVEL).toEqual(1); - expect(InternalNode1.NUM_VOXELS).toEqual(32_768); + expect(InternalNode1.NUM_VOXELS).toEqual(262_144); }); describe('setValueOn()', () => { @@ -50,28 +50,28 @@ describe('InternalNode', () => { describe('coordToOffset()', () => { it.each([ [[0, 0, LeafNode.DIM], 1], - [[0, LeafNode.DIM, LeafNode.DIM], 4 + 1], - [[LeafNode.DIM, LeafNode.DIM, LeafNode.DIM], 16 + 4 + 1], + [[0, LeafNode.DIM, LeafNode.DIM], 8 + 1], + [[LeafNode.DIM, LeafNode.DIM, LeafNode.DIM], 64 + 8 + 1], [[0, 0, LeafNode.DIM * 0], 0], [[0, 0, LeafNode.DIM * 1], 1], [[0, 0, LeafNode.DIM * 2], 2], [[0, 0, LeafNode.DIM * 3], 3], - [[0, LeafNode.DIM * 0, 0], 0 * 4], - [[0, LeafNode.DIM * 1, 0], 1 * 4], - [[0, LeafNode.DIM * 2, 0], 2 * 4], - [[0, LeafNode.DIM * 3, 0], 3 * 4], + [[0, LeafNode.DIM * 0, 0], 0 * 8], + [[0, LeafNode.DIM * 1, 0], 1 * 8], + [[0, LeafNode.DIM * 2, 0], 2 * 8], + [[0, LeafNode.DIM * 3, 0], 3 * 8], - [[LeafNode.DIM * 0, 0, 0], 0 * 16], - [[LeafNode.DIM * 1, 0, 0], 1 * 16], - [[LeafNode.DIM * 2, 0, 0], 2 * 16], - [[LeafNode.DIM * 3, 0, 0], 3 * 16], + [[LeafNode.DIM * 0, 0, 0], 0 * 64], + [[LeafNode.DIM * 1, 0, 0], 1 * 64], + [[LeafNode.DIM * 2, 0, 0], 2 * 64], + [[LeafNode.DIM * 3, 0, 0], 3 * 64], - // 24 / 8 = 3 -> 3 x 16 = 48 ╮ - // 9 / 8 = 1 -> 1 x 4 = 4 ├─> 48 + 4 + 2 = 54 - // 17 / 8 = 2 -> 2 x 1 = 2 ╯ - [[24, 9, 17], 54], + // 24 / 8 = 3 -> 3 x 64 = 192 ╮ + // 9 / 8 = 1 -> 1 x 8 = 8 ├─> 192 + 8 + 2 = 202 + // 17 / 8 = 2 -> 2 x 1 = 2 ╯ + [[24, 9, 17], 202], ])('should return for coordinate %j the offset (%j)', (xyz: Coord, offset: number) => { const child = new InternalNode1([0, 0, 0]); @@ -82,11 +82,12 @@ describe('InternalNode', () => { describe('isValueOn()', () => { it('should set each voxel', () => { const node1 = new InternalNode1([0, 0, 0]); + const maxDim = InternalNode1.DIM / 4; // Shorten test running time let onCounter = 0; - for (let x = 0; x < InternalNode1.DIM; x++) { - for (let y = 0; y < InternalNode1.DIM; y++) { - for (let z = 0; z < InternalNode1.DIM; z++) { + for (let x = 0; x < maxDim; x++) { + for (let y = 0; y < maxDim; y++) { + for (let z = 0; z < maxDim; z++) { node1.setValueOn([x, y, z], onCounter); expect(node1.getValue([x, y, z])).toEqual(onCounter); @@ -95,18 +96,19 @@ describe('InternalNode', () => { } } - expect(onCounter).toEqual(Math.pow(InternalNode1.DIM, 3)); + expect(onCounter).toEqual(Math.pow(maxDim, 3)); }); }); describe('onVoxelCount()', () => { it('should count all activated voxels', () => { const node1 = new InternalNode1([0, 0, 0]); + const maxDim = InternalNode1.DIM / 4; // Shorten test running time let onCounter = 0; - for (let x = 0; x < InternalNode1.DIM; x++) { - for (let y = 0; y < InternalNode1.DIM; y++) { - for (let z = 0; z < InternalNode1.DIM; z++) { + for (let x = 0; x < maxDim; x++) { + for (let y = 0; y < maxDim; y++) { + for (let z = 0; z < maxDim; z++) { node1.setValueOn([x, y, z], 42); onCounter++; @@ -115,7 +117,7 @@ describe('InternalNode', () => { } } - expect(onCounter).toEqual(Math.pow(InternalNode1.DIM, 3)); + expect(onCounter).toEqual(Math.pow(maxDim, 3)); }); }); @@ -143,11 +145,11 @@ describe('InternalNode', () => { describe('InternalNode2', () => { describe('static config values', () => { expect(InternalNode2.LOG2DIM).toEqual(2); - expect(InternalNode2.TOTAL).toEqual(7); - expect(InternalNode2.DIM).toEqual(128); + expect(InternalNode2.TOTAL).toEqual(2 + 3 + 3); + expect(InternalNode2.DIM).toEqual(256); expect(InternalNode2.NUM_VALUES).toEqual(64); expect(InternalNode2.LEVEL).toEqual(2); - expect(InternalNode2.NUM_VOXELS).toEqual(2_097_152); + expect(InternalNode2.NUM_VOXELS).toEqual(16_777_216); }); describe('setValueOn()', () => { @@ -176,14 +178,14 @@ describe('InternalNode', () => { describe('coordToOffset()', () => { it.each([ [[0, 0, 0], 0], - [[0, 0, 128], 0], - [[0, 0, 32], 1], - [[0, 0, 64], 2], - [[0, 0, 96], 3], - - [[0, 0, 32], 1], - [[0, 32, 0], 4], - [[32, 0, 0], 16], + [[0, 0, 256], 0], + [[0, 0, 64], 1], + [[0, 0, 128], 2], + [[0, 0, 192], 3], + + [[0, 0, 64], 1], + [[0, 64, 0], 4], + [[64, 0, 0], 16], ])('should return for coordinate %j the offset (%j)', (xyz: Coord, offset: number) => { const child = new InternalNode2([0, 0, 0]); @@ -194,18 +196,19 @@ describe('InternalNode', () => { describe('onVoxelCount()', () => { it('should count all activated voxels', () => { const node2 = new InternalNode2([0, 0, 0]); + const maxDim = InternalNode2.DIM / 4; // Shorten test running time let onCounter = 0; - for (let x = 0; x < InternalNode2.DIM; x++) { - for (let y = 0; y < InternalNode2.DIM; y++) { - for (let z = 0; z < InternalNode2.DIM; z++) { + for (let x = 0; x < maxDim; x++) { + for (let y = 0; y < maxDim; y++) { + for (let z = 0; z < maxDim; z++) { node2.setValueOn([x, y, z], 42); onCounter++; } } } - expect(onCounter).toEqual(Math.pow(InternalNode2.DIM, 3)); + expect(onCounter).toEqual(Math.pow(maxDim, 3)); }); }); diff --git a/libs/vdb/src/lib/tree/internal-node.ts b/libs/vdb/src/lib/tree/internal-node.ts index 306bce01..b877927e 100644 --- a/libs/vdb/src/lib/tree/internal-node.ts +++ b/libs/vdb/src/lib/tree/internal-node.ts @@ -8,9 +8,9 @@ import { ValueAccessor3 } from './value-accessor'; import { Voxel } from './voxel'; abstract class InternalNode implements HashableNode { + origin: Coord; protected childMask: NodeMask; protected valueMask: NodeMask; - protected origin: Coord; protected nodes: NodeUnion>[]; @@ -78,6 +78,23 @@ abstract class InternalNode implements HashableNode { return node.getValue(); } + probeInternalNode1AndCache( + xyz: Coord, + accessor: ValueAccessor3, + ): InternalNode1 | undefined { + const i: Index = this.coordToOffset(xyz); + const node = this.nodes[i]; + + if (this.childMask.isOff(i)) { + return undefined; + } + + const child = node.getChild(); + accessor.insert(xyz, child); + + return child instanceof InternalNode1 ? child : child.probeInternalNode1AndCache(xyz, accessor); + } + setValueOn(xyz: Coord, value: T): void { const i: Index = this.coordToOffset(xyz); const node = this.nodes[i]; @@ -242,7 +259,7 @@ abstract class InternalNode implements HashableNode { export class InternalNode1 extends InternalNode { // tslint:disable:no-bitwise - static readonly LOG2DIM = 2; // log2 of tile count in one dimension + static readonly LOG2DIM = 3; // log2 of tile count in one dimension static readonly TOTAL = InternalNode1.LOG2DIM + LeafNode.TOTAL; // log2 of voxel count in one dimension static readonly DIM = 1 << InternalNode1.TOTAL; // total voxel count in one dimension static readonly DIM_MAX_INDEX_INVERTED: Index = ~(InternalNode1.DIM - 1); // Performance: max index diff --git a/libs/vdb/src/lib/tree/leaf-node.ts b/libs/vdb/src/lib/tree/leaf-node.ts index 4cada089..6fbed000 100644 --- a/libs/vdb/src/lib/tree/leaf-node.ts +++ b/libs/vdb/src/lib/tree/leaf-node.ts @@ -1,5 +1,6 @@ import { Coord } from '../math/coord'; import { NodeMask } from '../util/node-mask'; +import { InternalNode1 } from './internal-node'; import { LeafBuffer } from './leaf-buffer'; import { HashableNode } from './node'; import { ValueAccessor3 } from './value-accessor'; @@ -21,12 +22,13 @@ export class LeafNode implements HashableNode { static readonly LEVEL: Index = 0; // level 0 = leaf // tslint:enable:no-bitwise + // Global grid index coordinates (x,y,z) of the local origin of this node + readonly origin: Coord; + // Buffer containing the actual data values private buffer: LeafBuffer; // Bitmask that determines which voxels are active private valueMask: NodeMask; - // Global grid index coordinates (x,y,z) of the local origin of this node - private readonly origin: Coord; /** * Return the linear table offset of the given global or local coordinates. @@ -119,6 +121,10 @@ export class LeafNode implements HashableNode { return this.getValue(xyz); } + probeInternalNode1AndCache(xyz: Coord, _: ValueAccessor3): InternalNode1 | undefined { + throw new Error(`Shouldn't be called on LeafNode`); + } + /** * @brief Change the value of the voxel at the given coordinates and mark it as active. * @note Used internally by ValueAccessor. diff --git a/libs/vdb/src/lib/tree/node.ts b/libs/vdb/src/lib/tree/node.ts index e4c34174..a4fff5bb 100644 --- a/libs/vdb/src/lib/tree/node.ts +++ b/libs/vdb/src/lib/tree/node.ts @@ -1,3 +1,4 @@ +import { InternalNode1 } from '@talus/vdb'; import { Coord } from '../math/coord'; import { ValueAccessor3 } from './value-accessor'; import { Voxel } from './voxel'; @@ -33,11 +34,18 @@ export interface HashableNode extends Node { */ getValueAndCache(xyz: Coord, accessor: ValueAccessor3): T; + /** + * Same as probeNode() except, if necessary, update the accessor with pointers + * to the nodes along the path from the root node to the node containing (x, y, z). + */ + probeInternalNode1AndCache(xyz: Coord, accessor: ValueAccessor3): InternalNode1 | undefined; + /** * Change the value of the voxel at the given coordinates and mark it as active. * If necessary, update the accessor with pointers to the nodes along the path * from the root node to the node containing the voxel. * @note Used internally by ValueAccessor. + * @return The affected `LeafNode` in which a value was set. */ setValueAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void; diff --git a/libs/vdb/src/lib/tree/root-node.ts b/libs/vdb/src/lib/tree/root-node.ts index 20d3dc9e..caabf4b5 100644 --- a/libs/vdb/src/lib/tree/root-node.ts +++ b/libs/vdb/src/lib/tree/root-node.ts @@ -1,5 +1,5 @@ import { Coord } from '../math/coord'; -import { InternalNode2 } from './internal-node'; +import { InternalNode1, InternalNode2 } from './internal-node'; import { HashableNode } from './node'; import { ValueAccessor3 } from './value-accessor'; import { Voxel } from './voxel'; @@ -57,6 +57,22 @@ export class RootNode implements HashableNode { return struct.getTile().value; } + probeInternalNode1AndCache( + xyz: Coord, + accessor: ValueAccessor3, + ): InternalNode1 | undefined { + const struct = this.findCoord(xyz); + + if (!struct || struct.isTile()) { + return undefined; + } + + const child = struct.getChild(); + accessor.insert(xyz, child); + + return child.probeInternalNode1AndCache(xyz, accessor); + } + setValueOn(xyz: Coord, value: T): void { const struct = this.findCoord(xyz); let child: HashableNode; @@ -92,7 +108,7 @@ export class RootNode implements HashableNode { if (child) { accessor.insert(xyz, child); - child.setValueOn(xyz, value); + child.setValueAndCache(xyz, value, accessor); } } diff --git a/libs/vdb/src/lib/tree/value-accessor.ts b/libs/vdb/src/lib/tree/value-accessor.ts index 9ba01796..4b881ff4 100644 --- a/libs/vdb/src/lib/tree/value-accessor.ts +++ b/libs/vdb/src/lib/tree/value-accessor.ts @@ -1,4 +1,4 @@ -import { Coord, createMaxCoord } from '../math/coord'; +import { clone, Coord, createMaxCoord } from '../math/coord'; import { InternalNode1, InternalNode2 } from './internal-node'; import { LeafNode } from './leaf-node'; import { HashableNode } from './node'; @@ -28,7 +28,9 @@ import { Tree } from './tree'; * The configuration is hard-coded and has a depth of four. */ export class ValueAccessor3 { - constructor(private tree: Tree) {} + get internalNode1Origin(): Coord { + return clone(this.internalKey1); + } private leafKey: Coord = createMaxCoord(); private leafNode: LeafNode; @@ -39,6 +41,8 @@ export class ValueAccessor3 { private internalKey2: Coord = createMaxCoord(); private internalNode2: InternalNode2; + constructor(private tree: Tree) {} + /** * Return true if any of the nodes along the path to the given voxel have been cached. */ @@ -46,6 +50,20 @@ export class ValueAccessor3 { return this.isHashed2(xyz) || this.isHashed1(xyz) || this.isHashed0(xyz); } + /** + * @returns Returns the node that contains voxel (x, y, z) + * and if it doesn't exist, return undefined. + */ + probeInternalNode1(xyz: Coord): InternalNode1 | undefined { + if (this.isHashed1(xyz)) { + return this.internalNode1; + } else if (this.isHashed2(xyz)) { + return this.internalNode2.probeInternalNode1AndCache(xyz, this); + } else { + return this.tree.root.probeInternalNode1AndCache(xyz, this); + } + } + /** * Return the value of the voxel at the given coordinates. */ From caa2751e7092a6d3707f4a6609aefe8a35b74351 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 8 Jan 2020 17:42:34 +0100 Subject: [PATCH 36/67] feat(benchmark): test single vs. multiple `array.push()` --- .../src/app/vdb/node-to-mesh.benchmark.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/benchmark/src/app/vdb/node-to-mesh.benchmark.ts diff --git a/apps/benchmark/src/app/vdb/node-to-mesh.benchmark.ts b/apps/benchmark/src/app/vdb/node-to-mesh.benchmark.ts new file mode 100644 index 00000000..b06dcd42 --- /dev/null +++ b/apps/benchmark/src/app/vdb/node-to-mesh.benchmark.ts @@ -0,0 +1,34 @@ +import { benchmark, suite } from '../../main'; + +suite('[NodeToMesh] array.push()', () => { + benchmark('multiple small push', () => { + const positions: number[] = []; + + positions.push(1); + positions.push(2); + positions.push(3); + positions.push(4); + positions.push(5); + positions.push(6); + positions.push(7); + positions.push(8); + positions.push(9); + positions.push(10); + positions.push(11); + positions.push(12); + positions.push(13); + positions.push(14); + positions.push(15); + positions.push(16); + positions.push(17); + positions.push(18); + positions.push(19); + positions.push(20); + }); + + benchmark('single big push', () => { + const positions: number[] = []; + + positions.push(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20); + }); +}); From 97be3c4787e44812b7239a0f3c6ad4dd8cc2b5af Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 8 Jan 2020 17:50:59 +0100 Subject: [PATCH 37/67] build(CircleCi): update node to `13.5.0` & cypress `3.8.1` --- .circleci/config.yml | 6 +++--- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 854fadfc..24488b48 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,17 +7,17 @@ aliases: # https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/node/images - &use_docker_node docker: - - image: circleci/node:13.4.0-stretch + - image: circleci/node:13.5.0-stretch - &use_docker_node_browsers docker: - - image: circleci/node:13.4.0-stretch-browsers + - image: circleci/node:13.5.0-stretch-browsers # https://github.com/cypress-io/cypress-docker-images/tree/master/included - &use_docker_cypress_included docker: # 3.8.0 fails with `Error: write EPIPE` when running `benchmark`!? - - image: cypress/included:3.7.0 + - image: cypress/included:3.8.1 - &workspace ~/talus diff --git a/package.json b/package.json index dd0b33a6..c4f774eb 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "babylonjs": "4.1.0-beta.12", "benchmark": "2.1.4", "codelyzer": "5.2.1", - "cypress": "3.7.0", + "cypress": "3.8.1", "dotenv": "8.2.0", "gh-pages": "2.1.1", "jasmine-marbles": "0.6.0", diff --git a/yarn.lock b/yarn.lock index 1d45ac82..2062f3a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3988,10 +3988,10 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress@3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.7.0.tgz#e2cd71b87b6ce0d4c72c6ea25da1005d75c1f231" - integrity sha512-o+vfRxqAba8TduelzfZQ4WHmj2yNEjaoO2EuZ8dZ9pJpuW+WGtBGheKIp6zkoQsp8ZgFe8OoHh1i2mY8BDnMAw== +cypress@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.1.tgz#7821084e0ead81d35ffa29f2141c977dfdfc2343" + integrity sha512-eLk5OpL/ZMDfQx9t7ZaDUAGVcvSOPTi7CG1tiUnu9BGk7caBiDhuFi3Tz/D5vWqH/Dl6Uh4X+Au4W+zh0xzbXw== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" From 797aef03b4a5bc5da25e0d45124bf499661982d1 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 9 Jan 2020 09:31:01 +0100 Subject: [PATCH 38/67] build(nx): nx migrate @nrwl/workspace (v8.11.0) - nx migrate --run-migrations=migrations.json --- apps/benchmark/tslint.json | 5 +- libs/vdb/tslint.json | 5 +- package.json | 10 +- yarn.lock | 229 +++++++++++++++++++++---------------- 4 files changed, 145 insertions(+), 104 deletions(-) diff --git a/apps/benchmark/tslint.json b/apps/benchmark/tslint.json index 04809f83..8e2f21b3 100644 --- a/apps/benchmark/tslint.json +++ b/apps/benchmark/tslint.json @@ -1 +1,4 @@ -{ "extends": "../../tslint.json", "rules": [] } +{ + "extends": "../../tslint.json", + "rules": {} +} diff --git a/libs/vdb/tslint.json b/libs/vdb/tslint.json index 04809f83..8e2f21b3 100644 --- a/libs/vdb/tslint.json +++ b/libs/vdb/tslint.json @@ -1 +1,4 @@ -{ "extends": "../../tslint.json", "rules": [] } +{ + "extends": "../../tslint.json", + "rules": {} +} diff --git a/package.json b/package.json index c4f774eb..689cc85c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@babylonjs/materials": "4.1.0-beta.12", "@ngrx/effects": "8.6.0", "@ngrx/store": "8.6.0", - "@nrwl/angular": "8.9.0", + "@nrwl/angular": "8.11.0", "core-js": "3.6.0", "hammerjs": "2.0.8", "mnemonist": "0.32.0", @@ -61,10 +61,10 @@ "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", "@babylonjs/inspector": "4.1.0-beta.12", - "@nrwl/cypress": "8.9.0", - "@nrwl/jest": "8.9.0", - "@nrwl/node": "8.9.0", - "@nrwl/workspace": "8.9.0", + "@nrwl/cypress": "8.11.0", + "@nrwl/jest": "8.11.0", + "@nrwl/node": "8.11.0", + "@nrwl/workspace": "8.11.0", "@types/benchmark": "1.0.31", "@types/jest": "24.0.24", "@types/node": "12.12.21", diff --git a/yarn.lock b/yarn.lock index 2062f3a3..1d0a9d17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1808,32 +1808,32 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@nrwl/angular@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/angular/-/angular-8.9.0.tgz#54b5bf31d969a8cd8a49f9e1a112f3d0fa7ac437" - integrity sha512-FxMKD3g5JQ3LwInRv1Pa8X1efG/nSoeBOTMbtEJs7CnaTonMWMPbY8QNSFidM8J+dWxOMDs9DXm5v66eOELpnw== +"@nrwl/angular@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/angular/-/angular-8.11.0.tgz#d65f8800acb852544fec4b11b0b49fe12bbb34b3" + integrity sha512-MIFwd2WdY8uvW1oySPzGxs2kYtprXIHYzXkkW3L5BMY0yVWTUqpUpmtMHQBPgA2E2OCIIO7jpccrXMRofMU57Q== dependencies: "@angular-devkit/schematics" "8.3.14" - "@nrwl/cypress" "8.9.0" - "@nrwl/jest" "8.9.0" + "@nrwl/cypress" "8.11.0" + "@nrwl/jest" "8.11.0" "@schematics/angular" "8.3.14" jasmine-marbles "~0.6.0" -"@nrwl/cli@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-8.9.0.tgz#5553d01909b75efc43e24ee3d5781243fbacbc9a" - integrity sha512-Z2ci9BQNsPeBfJTpXwMJ9NIfMLTEMsPoOXGxlCTjTZcpr6t2TlScVR9BIArgrv4BiMctyKUFRBxe6aX9eO98KA== +"@nrwl/cli@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-8.11.0.tgz#bb45b31c45409af706b2636798ec695a2c6104aa" + integrity sha512-S8z9wgeWObmRuCXWVrQ9yIeWnyJJ4CEIzmuSbs3k+XBx/MTP2QsoluJSYHv4NYxFM2hTboZPNuicNsz16Ua5/Q== dependencies: - "@nrwl/tao" "8.9.0" + "@nrwl/tao" "8.11.0" chalk "2.4.2" tmp "0.0.33" yargs "^11.0.0" yargs-parser "10.0.0" -"@nrwl/cypress@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/cypress/-/cypress-8.9.0.tgz#90016e1f9f4442436e5c3ce65d30923355d22210" - integrity sha512-xVTp5Lyy2HRYqJn3xwFJ85bzJiDygKuSm7ZXKJojCqg4ZwCBJDOoE3GzT/gYs1jRrKhV/jizkXkNtJA1UK2HZQ== +"@nrwl/cypress@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/cypress/-/cypress-8.11.0.tgz#d0771f9a5f4e1cb25c7230de6372d3da9d9adcf0" + integrity sha512-AB8Df+eX/qTR05EDswhk1hr9/RxNBe41mUzUq3KGvXEj7xMw+6Jt3JmBnoISk2olqDTB1DM3gLV0ytSC1FkktQ== dependencies: "@angular-devkit/architect" "0.803.14" "@angular-devkit/core" "8.3.14" @@ -1843,37 +1843,37 @@ tsconfig-paths-webpack-plugin "3.2.0" webpack-node-externals "1.7.2" -"@nrwl/jest@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-8.9.0.tgz#be8d07c0c3b10d918e119eaa8b51a14013c3cb97" - integrity sha512-Vi10aiIAsNb5xqedyPT173nQLhblfFZG/GleO+SkM9qXjRLm6n1KgFdiLuOI5V+mtU0UcCSd+SbI2uJsk19i2w== +"@nrwl/jest@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-8.11.0.tgz#ed02e7facc90c91bff0f6974a3d329d1e83ca9f4" + integrity sha512-EyuuNAItQDSwJNtsDTs7zINdRG9GjU2rnTJsonMdnsdZIikM0HD8xooF/XzdIqfbc5c7ZZ46LqCChQ8PhWqBhQ== dependencies: "@angular-devkit/architect" "0.803.14" "@angular-devkit/core" "8.3.14" "@angular-devkit/schematics" "8.3.14" -"@nrwl/linter@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/linter/-/linter-8.9.0.tgz#260a7ccaf9cc951042f5c23f480114a20794e0b8" - integrity sha512-e4mkAaR6BrgPWxw8YMhvuhIQUl7epm7rDnriZ3Y93DF/tfFNh5R5Hy57Nix52NDlnjP6kVcf2lxvrPSUi4iyrA== +"@nrwl/linter@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/linter/-/linter-8.11.0.tgz#9113d574dabfedda4059b8130e1299a95b4169c6" + integrity sha512-a66Hx84XJZTziiVNyqoan1lhcI10NFLfta0Sgk+9gGHuaT4KI3NjAhKSUNSchIlyN8enRb+Gl3Wenv2CHnqyJw== dependencies: "@angular-devkit/architect" "0.803.14" "@angular-eslint/builder" "0.0.1-alpha.17" -"@nrwl/node@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/node/-/node-8.9.0.tgz#91f7770053f67672fa53d207b0fa57220c147da4" - integrity sha512-wCKLdeUnlohPJ7B4m3YUrn727i7simRzeByfHbslxnY85U0PmbVkOZXs6RlQxAh0dErNAbDfgN+vRPESVn9Eng== +"@nrwl/node@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/node/-/node-8.11.0.tgz#8e21f869ef4b9139cc9bed0ae6ee19802f11888f" + integrity sha512-H4LXQO1TYn5XjTo5bEySzuNSzu/gIffWbm4DHX9Ilie2iRr1fBDLD+/oo5qNLGhLuFWM8o9gKG6FDpNAhI7B6g== dependencies: "@angular-devkit/architect" "0.803.14" "@angular-devkit/build-webpack" "0.803.14" "@angular-devkit/core" "8.3.14" "@angular-devkit/schematics" "8.3.14" - "@nrwl/jest" "8.9.0" - "@nrwl/linter" "8.9.0" + "@nrwl/jest" "8.11.0" + "@nrwl/linter" "8.11.0" circular-dependency-plugin "5.2.0" - copy-webpack-plugin "5.0.3" - fork-ts-checker-webpack-plugin "0.4.15" + copy-webpack-plugin "5.1.1" + fork-ts-checker-webpack-plugin "^3.1.1" license-webpack-plugin "2.1.2" source-map-support "0.5.12" tree-kill "1.2.1" @@ -1881,12 +1881,13 @@ tsconfig-paths-webpack-plugin "3.2.0" webpack "4.41.2" webpack-dev-server "3.9.0" + webpack-merge "4.2.1" webpack-node-externals "1.7.2" -"@nrwl/tao@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-8.9.0.tgz#f28a8a62e2613d30805fd85f2e9234fb01d39133" - integrity sha512-hAIw7J94qv+i+JMs6aB0ZS/eBOlYJ0L50VeaFWk2n94FmDNW4WFKIQRuNBM4CGcdpT+h1z3tR7QeWPjCaXk3Ow== +"@nrwl/tao@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-8.11.0.tgz#bf03d8825cccb06a7fd7d7c498b278deda882f78" + integrity sha512-9N+Vk/M8u1XVjMiLvtjEeFXYkb1TfSFvlKR0XyY7arCYmA/a6z594D4nUADjpDogNy2cyxBXcAjkKTOK1FSqZw== dependencies: "@angular-devkit/architect" "0.803.14" "@angular-devkit/core" "8.3.14" @@ -1896,21 +1897,21 @@ minimist "^1.2.0" strip-json-comments "2.0.1" -"@nrwl/workspace@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-8.9.0.tgz#4dc3d1ff9b34ce983158a5aa4bf3a0ef28c0df69" - integrity sha512-mwimmwx1V5kO9DXVygw++PoRhyIrut+LSQ3VGWu+ui9qwNQlcCLPwQQdHHp447qGdcb8Qne9ZPMHXUt8sWo5EQ== +"@nrwl/workspace@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-8.11.0.tgz#42b37098db2ad31047db1907169f6969907feee1" + integrity sha512-3cougMUedrOO8v1164i6I+mrGyDm1Uv2yFrYwMAnAcW+9s9Yy2KgEJ4HyBb4rJIhi7uKyQk9u9Q9QQtJsW+Kjg== dependencies: "@angular-devkit/core" "8.3.14" "@angular-devkit/schematics" "8.3.14" - "@nrwl/cli" "8.9.0" + "@nrwl/cli" "8.11.0" chalk "2.4.2" cosmiconfig "4.0.0" fs-extra "6.0.0" + hasha "5.1.0" ignore "5.0.4" npm-run-all "4.1.5" opn "^5.3.0" - prettier "1.18.2" rxjs "^6.4.0" semver "5.4.1" strip-json-comments "2.0.1" @@ -2477,6 +2478,14 @@ anymatch@^3.0.1: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + app-root-path@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" @@ -2977,7 +2986,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@^3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -3176,26 +3185,6 @@ cacache@12.0.2, cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^11.3.2: - version "11.3.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc" - integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - cacache@^12.0.0, cacache@^12.0.3: version "12.0.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" @@ -3416,7 +3405,7 @@ chokidar@^2.0.2, chokidar@^2.1.1: optionalDependencies: fsevents "^1.2.7" -chokidar@^2.0.4, chokidar@^2.1.8: +chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -3435,6 +3424,21 @@ chokidar@^2.0.4, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" + integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.3.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" @@ -3762,24 +3766,6 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-webpack-plugin@5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.3.tgz#2179e3c8fd69f13afe74da338896f1f01a875b5c" - integrity sha512-PlZRs9CUMnAVylZq+vg2Juew662jWtwOXOqH4lbQD9ZFhRG9R7tVStOgHt21CBGVq7k5yIJaz8TXDLSjV+Lj8Q== - dependencies: - cacache "^11.3.2" - find-cache-dir "^2.1.0" - glob-parent "^3.1.0" - globby "^7.1.1" - is-glob "^4.0.1" - loader-utils "^1.2.3" - minimatch "^3.0.4" - normalize-path "^3.0.0" - p-limit "^2.2.0" - schema-utils "^1.0.0" - serialize-javascript "^1.7.0" - webpack-log "^2.0.0" - copy-webpack-plugin@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" @@ -5027,19 +5013,19 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.4.15.tgz#7cd9f94f3dd58cd1fe8f953f876e72090eda3f6d" - integrity sha512-qNYuygh2GxXehBvQZ5rI5YlQFn+7ZV6kmkyD9Sgs33dWl73NZdUOB5aCp8v0EXJn176AhPrZP8YCMT3h01fs+g== +fork-ts-checker-webpack-plugin@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz#a1642c0d3e65f50c2cc1742e9c0a80f441f86b19" + integrity sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" - chokidar "^2.0.4" - lodash "^4.17.11" + chokidar "^3.3.0" micromatch "^3.1.10" minimatch "^3.0.4" - resolve "^1.5.0" + semver "^5.6.0" tapable "^1.0.0" + worker-rpc "^0.1.0" form-data@~2.3.2: version "2.3.3" @@ -5137,6 +5123,11 @@ fsevents@^2.0.6: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a" integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ== +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -5236,6 +5227,13 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" +glob-parent@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -5472,6 +5470,14 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasha@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.1.0.tgz#dd05ccdfcfe7dab626247ce2a58efe461922f4ca" + integrity sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -5896,7 +5902,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-binary-path@^2.1.0: +is-binary-path@^2.1.0, is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== @@ -6032,7 +6038,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -6129,6 +6135,11 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" @@ -7349,6 +7360,11 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= +microevent.ts@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" + integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7751,7 +7767,7 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -8366,6 +8382,11 @@ picomatch@^2.0.4, picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== +picomatch@^2.0.7: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + pidtree@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" @@ -8603,11 +8624,6 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -prettier@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== - prettier@1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" @@ -8945,6 +8961,13 @@ readdirp@^3.1.1: dependencies: picomatch "^2.0.4" +readdirp@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" + integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== + dependencies: + picomatch "^2.0.7" + realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -9247,7 +9270,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@1.x, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.5.0: +resolve@1.x, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== @@ -10707,6 +10730,11 @@ type-fest@^0.5.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -11319,6 +11347,13 @@ worker-plugin@3.2.0: dependencies: loader-utils "^1.1.0" +worker-rpc@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5" + integrity sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg== + dependencies: + microevent.ts "~0.1.1" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" From e50fa260bef4aa6a9699c8d5584c7ed17efe318c Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 9 Jan 2020 10:57:12 +0100 Subject: [PATCH 39/67] fix(benchmark): add `.nxignore` to get benchmark through linter --- .nxignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .nxignore diff --git a/.nxignore b/.nxignore new file mode 100644 index 00000000..34902dd4 --- /dev/null +++ b/.nxignore @@ -0,0 +1,2 @@ +# Hack for getting benchmark app (generated with ng g @nrwl/node:application) through linting +/apps/benchmark From 22b39b69bfdaa312a89a161bcf3a185c2176239c Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 9 Jan 2020 11:06:55 +0100 Subject: [PATCH 40/67] build(dep): update dependencies --- .../lib/scene-viewer/scene-viewer.service.ts | 2 +- package.json | 26 +- yarn.lock | 317 ++++++++++-------- 3 files changed, 187 insertions(+), 158 deletions(-) diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index cc507dec..451bfbc2 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -115,7 +115,7 @@ export class SceneViewerService { // https://doc.babylonjs.com/how_to/optimizing_your_scene this.scene = new Scene(this.engine, { useGeometryUniqueIdsMap: true, - useClonedMeshhMap: true, + useClonedMeshMap: true, }); this.scene.freezeMaterials(); diff --git a/package.json b/package.json index 689cc85c..c7ed7855 100644 --- a/package.json +++ b/package.json @@ -44,48 +44,48 @@ "@angular/platform-browser": "8.2.14", "@angular/platform-browser-dynamic": "8.2.14", "@angular/router": "8.2.14", - "@babylonjs/core": "4.1.0-beta.12", - "@babylonjs/materials": "4.1.0-beta.12", + "@babylonjs/core": "4.1.0-beta.18", + "@babylonjs/materials": "4.1.0-beta.18", "@ngrx/effects": "8.6.0", "@ngrx/store": "8.6.0", "@nrwl/angular": "8.11.0", - "core-js": "3.6.0", + "core-js": "3.6.2", "hammerjs": "2.0.8", "mnemonist": "0.32.0", - "rxjs": "6.5.3", + "rxjs": "6.5.4", "zone.js": "0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "0.803.21", - "@angular/cli": "8.3.21", + "@angular-devkit/build-angular": "0.803.22", + "@angular/cli": "8.3.22", "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", - "@babylonjs/inspector": "4.1.0-beta.12", + "@babylonjs/inspector": "4.1.0-beta.18", "@nrwl/cypress": "8.11.0", "@nrwl/jest": "8.11.0", "@nrwl/node": "8.11.0", "@nrwl/workspace": "8.11.0", "@types/benchmark": "1.0.31", - "@types/jest": "24.0.24", - "@types/node": "12.12.21", - "babylonjs": "4.1.0-beta.12", + "@types/jest": "24.0.25", + "@types/node": "13.1.5", + "babylonjs": "4.1.0-beta.18", "benchmark": "2.1.4", "codelyzer": "5.2.1", "cypress": "3.8.1", "dotenv": "8.2.0", - "gh-pages": "2.1.1", + "gh-pages": "2.2.0", "jasmine-marbles": "0.6.0", "jest": "24.9.0", "jest-junit": "10.0.0", "jest-preset-angular": "7.1.1", "junit-xml": "1.2.0", "prettier": "1.19.1", - "stylelint": "12.0.0", + "stylelint": "12.0.1", "stylelint-config-recommended": "3.0.0", "stylelint-config-recommended-scss": "4.1.0", "stylelint-config-standard": "19.0.0", "stylelint-scss": "3.13.0", - "ts-jest": "24.2.0", + "ts-jest": "24.3.0", "ts-node": "8.5.4", "tslint": "5.20.1", "typescript": "3.5.3" diff --git a/yarn.lock b/yarn.lock index 1d0a9d17..edf45950 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,31 +10,31 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/architect@0.803.21": - version "0.803.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.803.21.tgz#0e76b6f646ebdbd9bb88d3972b2ca66fed950f7d" - integrity sha512-E2K/YexIWVyKM/xmyxvDjkJf+wX9u4c8YYpNaK4htsRzA06juc7N1MhlL/jURZiRl5b/K9sapYeq3tMX76saxA== +"@angular-devkit/architect@0.803.22": + version "0.803.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.803.22.tgz#33b54099298aaef5f93ffefb8b91a98ea9f85387" + integrity sha512-5Gr0LH+Hjd/NLdmi660VBoo3WbzQM7/yeG+ziktb7hbeVaYK4Mejtcg/DJnCoZ3hzlZuZokWVwvpdFo+A9xKbg== dependencies: - "@angular-devkit/core" "8.3.21" + "@angular-devkit/core" "8.3.22" rxjs "6.4.0" -"@angular-devkit/build-angular@0.803.21": - version "0.803.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.803.21.tgz#f3d12ea09748b05eb2d835a7de7997599fb6b752" - integrity sha512-flfgflvfpwdsm3x/U7QnfbtyZPEbsVipzQAoao1Zo58Beq1a+NsKsWbjrF/x4TSoI2czt0OVWXNytlfXM7LMhg== +"@angular-devkit/build-angular@0.803.22": + version "0.803.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.803.22.tgz#0fa668e84c237c6b1ab524e50b0ccaedc3a92929" + integrity sha512-2q9qLsD52D4GACUAuQhvkgQ7vLAhZzdU0jzfs74RTxqUZ3PS6Ltrrwpdg2kp9RlQ53+nSCYjWBDLk1CxoEt4pg== dependencies: - "@angular-devkit/architect" "0.803.21" - "@angular-devkit/build-optimizer" "0.803.21" - "@angular-devkit/build-webpack" "0.803.21" - "@angular-devkit/core" "8.3.21" + "@angular-devkit/architect" "0.803.22" + "@angular-devkit/build-optimizer" "0.803.22" + "@angular-devkit/build-webpack" "0.803.22" + "@angular-devkit/core" "8.3.22" "@babel/core" "7.7.5" "@babel/preset-env" "7.7.6" - "@ngtools/webpack" "8.3.21" + "@ngtools/webpack" "8.3.22" ajv "6.10.2" autoprefixer "9.6.1" - browserslist "4.6.6" + browserslist "4.8.3" cacache "12.0.2" - caniuse-lite "1.0.30000989" + caniuse-lite "1.0.30001019" circular-dependency-plugin "5.2.0" clean-css "4.2.1" copy-webpack-plugin "5.1.1" @@ -80,10 +80,10 @@ webpack-subresource-integrity "1.1.0-rc.6" worker-plugin "3.2.0" -"@angular-devkit/build-optimizer@0.803.21": - version "0.803.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.803.21.tgz#ecb3b6bba4b13ffbfbdbefb5997f690aa3635203" - integrity sha512-gNN6kPaF4phZco3TmsrNr9tIEKXYsoSeoaUiDUfgmCYwa7fAqM8Ojh7HX6IQuB2PpVmEwKGlCcSh6xDtB33NjA== +"@angular-devkit/build-optimizer@0.803.22": + version "0.803.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.803.22.tgz#6d09cbb5fd28ab7bd22ddc54e938f305dfff8b20" + integrity sha512-VIDeQcBn88PjHBTen3BRVA7DJiKEJdDwukx61mUvUDOcY7S5Ot5WqG0nrZifRjha17Z+fl3XuwS9TZNYmlF7WQ== dependencies: loader-utils "1.2.3" source-map "0.7.3" @@ -100,13 +100,13 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/build-webpack@0.803.21": - version "0.803.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.803.21.tgz#fd45754c0123f44fcde8fa6411ebea52d98054f0" - integrity sha512-zCFVla/Xdk8qGVybvnHtoKml2h0/ShasSjT55VNZO1XaTCMqYkQEwwqSGEiVajpauafWjKrKxxBhsmWoI4efAA== +"@angular-devkit/build-webpack@0.803.22": + version "0.803.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.803.22.tgz#079b2ded794308b2dc93769406bdb0a1e32015c0" + integrity sha512-RDLAhKHfTFzthzeawHEefYB1MxHiU2I32QzXI3XTCpR2XySw5JG9jIVIcsyDHQH1JtIfpHGq8vgfiTsE3r0YWA== dependencies: - "@angular-devkit/architect" "0.803.21" - "@angular-devkit/core" "8.3.21" + "@angular-devkit/architect" "0.803.22" + "@angular-devkit/core" "8.3.22" rxjs "6.4.0" "@angular-devkit/core@8.3.14": @@ -120,10 +120,10 @@ rxjs "6.4.0" source-map "0.7.3" -"@angular-devkit/core@8.3.21": - version "8.3.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.21.tgz#447022813e46333e930816c287722d06b9c4dd3a" - integrity sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA== +"@angular-devkit/core@8.3.22": + version "8.3.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.3.22.tgz#085cc1cf356cec00d0a1cea83ef1f21277f5ff55" + integrity sha512-lOEYcvK3MktjR9YZT/cUjiQE5dZxl8rZ/vgWgwDiL7RtzfXTt8lPapoJe7YKS53gLbUYiBNPCtTyTAqnslWgGA== dependencies: ajv "6.10.2" fast-json-stable-stringify "2.0.0" @@ -139,12 +139,12 @@ "@angular-devkit/core" "8.3.14" rxjs "6.4.0" -"@angular-devkit/schematics@8.3.21": - version "8.3.21" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.21.tgz#80d515f480180be18a4130ea691f90153bcab3ea" - integrity sha512-+wH0362CRr/SijVX4w2baY2ANZ4scQ1k2xO8lT+NMeZQkw3IJQPOfwk1IaqiAs2xuBJZcSDH1Gn80+Jh4Dit7w== +"@angular-devkit/schematics@8.3.22": + version "8.3.22" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.3.22.tgz#41461768cc6cf54708d55311e59b9defa7bff484" + integrity sha512-ETLdV1ftT+ZuuiHl6FjFQ4XLQznWMcxWognX+qgByn+DQOXsYRRvZK1L5eG/SG8CKJ8NL5oteTDloDnghARHFw== dependencies: - "@angular-devkit/core" "8.3.21" + "@angular-devkit/core" "8.3.22" rxjs "6.4.0" "@angular-eslint/builder@0.0.1-alpha.17": @@ -168,16 +168,16 @@ optionalDependencies: parse5 "^5.0.0" -"@angular/cli@8.3.21": - version "8.3.21" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-8.3.21.tgz#cbb05b86b7f34ecd81d52ccad922359e66a16a15" - integrity sha512-ZZpA7mMfIobFT06rBNxm8vucAh8W2s0huJZ4iL0BPujnhIr71PL+gDwssySWDEz2q6i4CkH9QRH76DHhtL6VSQ== +"@angular/cli@8.3.22": + version "8.3.22" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-8.3.22.tgz#2512e0aeaffdbb30ace35dc288eeba9a86f28b95" + integrity sha512-OT2rzwnxwI0ETP7rXCxjxsIAZEYo9wHP/5rRbu3m15GlQ3Bclq34ZDRwC/bRxXL5+1DfmhAs9AjtYNoFoDM4Tg== dependencies: - "@angular-devkit/architect" "0.803.21" - "@angular-devkit/core" "8.3.21" - "@angular-devkit/schematics" "8.3.21" - "@schematics/angular" "8.3.21" - "@schematics/update" "0.803.21" + "@angular-devkit/architect" "0.803.22" + "@angular-devkit/core" "8.3.22" + "@angular-devkit/schematics" "8.3.22" + "@schematics/angular" "8.3.22" + "@schematics/update" "0.803.22" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "^4.1.1" @@ -1534,58 +1534,58 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babylonjs/core@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.12.tgz#9aaaa51fa4fc72defb9e444d8376294f3bccbb0b" - integrity sha512-o5IUXJJWwZpON4YRytvYJkdhuKVf5Kf8bieotp4TVqo+ECB+mUGvxkDFoa/Mc1A0QLT7YcDSuibYQbu6asRrTQ== +"@babylonjs/core@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.18.tgz#8d4cde4e8c791f1ff979d3a95834fcb78980970b" + integrity sha512-P4k/9aMmiMPU8YG+zJy0PZRog0cOqSplApHa8KtqdexILdQECM09jpFmv4ql2SCKXF643TD4+Iqv56TXzqfuDw== dependencies: tslib "^1.10.0" -"@babylonjs/gui@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.12.tgz#b467209fde28479e340dd0db107736b0334ae6a3" - integrity sha512-7WjS0liqvtSnJKqCR3ft2cwyOlqFiAUDQwzsSax4f1Iq9ql4M5J5+LC0FLXgkAGiltut8JjioSdEG39kD3T0TA== +"@babylonjs/gui@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.18.tgz#43142a5b32c49e1453aa61a7cbe359b3c8f4af56" + integrity sha512-onsQLXTp9jipvlBcy34U9U1Du6fM2IGcBzFt0aU27rpsKSNauLcveKP8oteHluNRqBWRHranoLDeipnEy0rGbQ== dependencies: - "@babylonjs/core" "4.1.0-beta.12" + "@babylonjs/core" "4.1.0-beta.18" tslib "^1.10.0" -"@babylonjs/inspector@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.12.tgz#c2e489b2a6a29d65523eec93a44346b1e65c97ec" - integrity sha512-Wga2Q5Gu5CBiR3zNMV30hCeTlDt5DxOGogOmMlkU9IfXg84VcpgjjHa4a1NV/nDaJtOP+sANKIvxVyAgtMhhhQ== - dependencies: - "@babylonjs/core" "4.1.0-beta.12" - "@babylonjs/gui" "4.1.0-beta.12" - "@babylonjs/loaders" "4.1.0-beta.12" - "@babylonjs/materials" "4.1.0-beta.12" - "@babylonjs/serializers" "4.1.0-beta.12" - babylonjs-gltf2interface "4.1.0-beta.12" +"@babylonjs/inspector@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.18.tgz#a42b0ce0baae40f5b0d67752dbe98b988199561e" + integrity sha512-1/bNWlqjZZ5uTwByuXhtRRwnA2WKXb6F1YFRJHIJ0ZtdW94y+UNzY43pBVQVD1A/7fY2G9P9tbdP0OF4M/JdLA== + dependencies: + "@babylonjs/core" "4.1.0-beta.18" + "@babylonjs/gui" "4.1.0-beta.18" + "@babylonjs/loaders" "4.1.0-beta.18" + "@babylonjs/materials" "4.1.0-beta.18" + "@babylonjs/serializers" "4.1.0-beta.18" + babylonjs-gltf2interface "4.1.0-beta.18" tslib "^1.10.0" -"@babylonjs/loaders@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.12.tgz#a0225a705507705ca9d4730eede87c95aa4b84c7" - integrity sha512-FIZxjltGLMP3DSCtos365HjPpL7zOfzkERe+X5/yy9zkMKPrzZGcKv90MZyEx+9lrjMTV3sueDMNTnp6d9pc/g== +"@babylonjs/loaders@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.18.tgz#09cd54ad6440570e8b024b515b1f739c471c8f58" + integrity sha512-Dsh4pxVFoqIeg1A5hWN281QSPotWMroqSMS3Zrm7KejKvdcT9J4NqFneYyMSMZyBBIMCdoYAdsF2w1gfkWW9ww== dependencies: - "@babylonjs/core" "4.1.0-beta.12" - babylonjs-gltf2interface "4.1.0-beta.12" + "@babylonjs/core" "4.1.0-beta.18" + babylonjs-gltf2interface "4.1.0-beta.18" tslib "^1.10.0" -"@babylonjs/materials@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.12.tgz#71dfe537b54c243e8c7db0a46683986c6d284008" - integrity sha512-lwJ6SZySiQiT+dijkg3yddgU71sGzmiO2Zm8JzSsRJkuA2P6K8s1sZUDVAhI5h6Im8i7LiSFWLPQQjZsDaOAkA== +"@babylonjs/materials@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.18.tgz#7a3e01eff726041a59e13f84fb89099bd629cec9" + integrity sha512-iC3qvwLfMkKDO8ALRiw1xqTjaXoaDPGuKvN6SIZQYTgnBTGLt+Zl6wZ6Org76QwUdqyOwgnyJasg+m56SgmY9g== dependencies: - "@babylonjs/core" "4.1.0-beta.12" + "@babylonjs/core" "4.1.0-beta.18" tslib "^1.10.0" -"@babylonjs/serializers@4.1.0-beta.12": - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.12.tgz#0c5f6a0050af4a6b7384a6d3dcb34a8f496ea58a" - integrity sha512-T2YWPPgj6voKowx9YanPTaFqPatxfBR3oVm/uPtt2iRFvt8POy1wYWBBzjFHRJKicQflhA2LEfHWFr82xyzCCg== +"@babylonjs/serializers@4.1.0-beta.18": + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.18.tgz#1a36debb01d59b67fc7ff6cfec318eb215bc0548" + integrity sha512-U12cY43vIZf5ULvPt6A6pDp8meYdabHjSAsPExulRLy6cxhbZcWLJrXBif6ugKOz8y1Ow8GiPO0NtPVbfl8YBg== dependencies: - "@babylonjs/core" "4.1.0-beta.12" - babylonjs-gltf2interface "4.1.0-beta.12" + "@babylonjs/core" "4.1.0-beta.18" + babylonjs-gltf2interface "4.1.0-beta.18" tslib "^1.10.0" "@cnakazawa/watch@^1.0.3": @@ -1792,12 +1792,12 @@ resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-8.6.0.tgz#8540c5bd40b33fc2f443e7e86f47c0d801b8f413" integrity sha512-K4cvCEa+5hw9qrETQWO+Cha3YbVCAT8yaIKJr/N35KntTL9mQMjoL+51JWLZfBwPV0e19CFgJIyrBnVUTxwr2A== -"@ngtools/webpack@8.3.21": - version "8.3.21" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-8.3.21.tgz#d28f2b66a8aeced5260c42ae722192ec5d5e4e56" - integrity sha512-DGqmFQ52sV4uB3y3spQTNLa69oU5cwd1yIqMB4GSM+Qp+hozdzrPA2gVH90N2DDhWe8icsSQHAtZQiR9+BDL8g== +"@ngtools/webpack@8.3.22": + version "8.3.22" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-8.3.22.tgz#f6792d66430fb48c890a8145dee5088e3519860b" + integrity sha512-MES7Q0k6GpQEY74cxElUVy7jIaDBSLvY+eOUN2GKL5CznvBSp3+U5px6X7ZjPGzCp7no1L1JkV9g2e0hPatlcw== dependencies: - "@angular-devkit/core" "8.3.21" + "@angular-devkit/core" "8.3.22" enhanced-resolve "4.1.0" rxjs "6.4.0" tree-kill "1.2.1" @@ -1927,21 +1927,21 @@ "@angular-devkit/core" "8.3.14" "@angular-devkit/schematics" "8.3.14" -"@schematics/angular@8.3.21": - version "8.3.21" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-8.3.21.tgz#4902e0b6e8be47006859009bf96a026e3d39dd27" - integrity sha512-KahQ+dHvTsGOZwY6IdzqJZLDEn0G89rrK3OY+7okZujoaLM+LXhxlPoznW1udnZJVTa3VNxYGx11fkgLtRJRqA== +"@schematics/angular@8.3.22": + version "8.3.22" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-8.3.22.tgz#fab009312bd3d50115332f2c41a92e15744ac09f" + integrity sha512-vD+UgPdbEoFPOH6xe2laFpHn/MC9R5C4A/+J9yQ6HBg5kt1YdyIBakvPOcXQCyWr5VZzDmTyMO76rd3zaef3DQ== dependencies: - "@angular-devkit/core" "8.3.21" - "@angular-devkit/schematics" "8.3.21" + "@angular-devkit/core" "8.3.22" + "@angular-devkit/schematics" "8.3.22" -"@schematics/update@0.803.21": - version "0.803.21" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.803.21.tgz#572c955bb132348bca03a128491ae264b0068a0a" - integrity sha512-D3BRvEBF2cJEgogvFaNOfqtTFHHv/ctSRfOeAYWjUxILtb+2DpuZ9h5QYDFhN9MPgz/vRaOqFORa3sEZCRkX4g== +"@schematics/update@0.803.22": + version "0.803.22" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.803.22.tgz#88b2fd3c5c2e3c5b2f453b912b281df14c94fd34" + integrity sha512-X+1sJ7YadcYxDqcLX7l7MEAIL3SHIXpCqToQdAZbAE06NdTFvg5eqiKreSdmm7ZdfL0dBe6oXi/yCDVMoL2zcw== dependencies: - "@angular-devkit/core" "8.3.21" - "@angular-devkit/schematics" "8.3.21" + "@angular-devkit/core" "8.3.22" + "@angular-devkit/schematics" "8.3.22" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" pacote "9.5.5" @@ -2026,10 +2026,10 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@24.0.24": - version "24.0.24" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.24.tgz#0f2f523dc77cc1bc6bef34eaf287ede887a73f05" - integrity sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ== +"@types/jest@24.0.25": + version "24.0.25" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f" + integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g== dependencies: jest-diff "^24.3.0" @@ -2048,10 +2048,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== -"@types/node@12.12.21": - version "12.12.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" - integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== +"@types/node@13.1.5": + version "13.1.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.5.tgz#4d5efc52a1d3e45d13e5ec9f911cbc5b089ccaec" + integrity sha512-wupvfmtbqRJzjCm1H2diy7wo31Gn1OzvqoxCfQuKM9eSecogzP0WTlrjdq7cf7jgSO2ZX6hxwgRPR8Wt7FA22g== "@types/parse-json@^4.0.0": version "4.0.0" @@ -2846,15 +2846,15 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -babylonjs-gltf2interface@4.1.0-beta.12: - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.12.tgz#38dbc4d3b48e76d4b29d9508092d62eb17e4ae26" - integrity sha512-BOLX7C2elDVd9UtJXPnOF7qMCy7LebtpySCEnhlsZDvCIVWqBhQgzXA/d3Oeb4tGtpiZtaB87WG2bzuLWL0FzA== +babylonjs-gltf2interface@4.1.0-beta.18: + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.18.tgz#afc333500bc60066d364769f17b1bddb540754b0" + integrity sha512-DIsZ0/NhmQ9XI7mPcvqfwCdhZn6l6yiJWvHMmsTFLHaIaVUhDiUomjxAF4yPIYeX2PbtmxkJpv4TJY7QnXF9MA== -babylonjs@4.1.0-beta.12: - version "4.1.0-beta.12" - resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.12.tgz#f42d88d865c9ba984506afde3b054dec215af092" - integrity sha512-SyQVqarSuBDAmIkIzGctb35XSwuRAv+vI9CaE5rz4ls35pbvPdj0Nf3sZUePUDw6CZueRp3z2sL+zgPuvbg3Ow== +babylonjs@4.1.0-beta.18: + version "4.1.0-beta.18" + resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.18.tgz#e0c2bfe10d960adba1c5425c3c4b77c5b5fc48da" + integrity sha512-9hblkZ5Y0n16e4SBDMIglsMRpvMuLgE2IvqoTOhWHWLMJX6jtX75ZnLhBFjGIjlvO3L18H1vCUQRgIcS29wotg== bail@^1.0.0: version "1.0.4" @@ -3069,7 +3069,16 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.6.6, browserslist@^4.6.0, browserslist@^4.6.3, browserslist@^4.6.6: +browserslist@4.8.3: + version "4.8.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44" + integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg== + dependencies: + caniuse-lite "^1.0.30001017" + electron-to-chromium "^1.3.322" + node-releases "^1.1.44" + +browserslist@^4.6.0, browserslist@^4.6.3, browserslist@^4.6.6: version "4.6.6" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA== @@ -3276,7 +3285,12 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@1.0.30000989, caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984: +caniuse-lite@1.0.30001019: + version "1.0.30001019" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz#857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1" + integrity sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g== + +caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984: version "1.0.30000989" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== @@ -3291,6 +3305,11 @@ caniuse-lite@^1.0.30001015: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz#16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66" integrity sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA== +caniuse-lite@^1.0.30001017: + version "1.0.30001020" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001020.tgz#3f04c1737500ffda78be9beb0b5c1e2070e15926" + integrity sha512-yWIvwA68wRHKanAVS1GjN8vajAv7MBFshullKCeq/eKpK7pJBVDgFFEqvgWTkcP2+wIDeQGYFRXECjKZnLkUjA== + canonical-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" @@ -3805,10 +3824,10 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.0.tgz#2b854e451de1967d1e29896025cdc13a2518d9ea" - integrity sha512-AHPTNKzyB+YwgDWoSOCaid9PUSEF6781vsfiK8qUz62zRR448/XgK2NtCbpiUGizbep8Lrpt0Du19PpGGZvw3Q== +core-js@3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.2.tgz#2799ea1a59050f0acf50dfe89b916d6503b16caa" + integrity sha512-hIE5dXkRzRvnZ5vhkRfQxUvDxQZmD9oueA08jDYRBKJHx+VIl/Pne/e0A4x9LObEEthC/TqiZybUoNM4tRgnKg== core-js@^2.4.0: version "2.6.9" @@ -5079,12 +5098,12 @@ fs-extra@6.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: - graceful-fs "^4.1.2" + graceful-fs "^4.2.0" jsonfile "^4.0.0" universalify "^0.1.0" @@ -5198,19 +5217,17 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -gh-pages@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.1.1.tgz#5be70a92f9cb70404bafabd8bb149c0e9a8c264b" - integrity sha512-yNW2SFp9xGRP/8Sk2WXuLI/Gn92oOL4HBgudn6PsqAnuWT90Y1tozJoTfX1WdrDSW5Rb90kLVOf5mm9KJ/2fDw== +gh-pages@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.2.0.tgz#74ebeaca8d2b9a11279dcbd4a39ddfff3e6caa24" + integrity sha512-c+yPkNOPMFGNisYg9r4qvsMIjVYikJv7ImFOhPIVPt0+AcRUamZ7zkGRLHz7FKB0xrlZ+ddSOJsZv9XAFVXLmA== dependencies: async "^2.6.1" commander "^2.18.0" email-addresses "^3.0.1" filenamify-url "^1.0.0" - fs-extra "^7.0.0" + fs-extra "^8.1.0" globby "^6.1.0" - graceful-fs "^4.1.11" - rimraf "^2.6.2" glob-parent@^3.1.0: version "3.1.0" @@ -5350,6 +5367,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== +graceful-fs@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -7742,6 +7764,13 @@ node-releases@^1.1.42: dependencies: semver "^6.3.0" +node-releases@^1.1.44: + version "1.1.45" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.45.tgz#4cf7e9175d71b1317f15ffd68ce63bce1d53e9f2" + integrity sha512-cXvGSfhITKI8qsV116u2FTzH5EWZJfgG7d4cpqwF8I8+1tWpD6AsvvGRKq2onR0DNj1jfqsjkXZsm14JMS7Cyg== + dependencies: + semver "^6.3.0" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -9363,10 +9392,10 @@ rxjs@6.4.0: dependencies: tslib "^1.9.0" -rxjs@6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== +rxjs@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: tslib "^1.9.0" @@ -10206,10 +10235,10 @@ stylelint-scss@3.13.0: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.2" -stylelint@12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-12.0.0.tgz#2e8613675f7be11769ce474f45137fdf7751380a" - integrity sha512-TwqtATrFOT07SPlUGyHN7tVhWqxwitn5BlAvyBQy/ekA+Nwu4mLU9L1dvGQPNxHUBLowjvkSW18QzHHR6/FVVQ== +stylelint@12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-12.0.1.tgz#5b1f3bf7333320acce322b49852c8b85e94ce7e4" + integrity sha512-1mn39pqZiC/e8KUPoRMc1WMM83Upb2ILaSGxkCvKxALHutEOs2txcPQocJiXdO4Zx4FY4prGqjlkwrbthAxqig== dependencies: autoprefixer "^9.7.1" balanced-match "^1.0.0" @@ -10586,10 +10615,10 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e" integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q== -ts-jest@24.2.0: - version "24.2.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.2.0.tgz#7abca28c2b4b0a1fdd715cd667d65d047ea4e768" - integrity sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag== +ts-jest@24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.3.0.tgz#b97814e3eab359ea840a1ac112deae68aa440869" + integrity sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ== dependencies: bs-logger "0.x" buffer-from "1.x" From 088dbed479955645724899d43249d048ca3de7f3 Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Mon, 13 Jan 2020 09:44:36 +0100 Subject: [PATCH 41/67] feat(frontend): add undo/redo & enable `strictNullChecks` (#10) * feat(frontend): add undo/redo & enforce `strictNullChecks` * feat(frontend): undo/redo with max buffer size * test(frontend): handle possible `undefined` * feat(frontend): make remove a voxel undoable * feat(frontend): place initial voxel at [0, 0, 0] * fix(frontend): dispose previous history if new `addUndo` * refactor(frontend): extract method for creating `addUndo` --- apps/benchmark/src/main.ts | 4 +- apps/frontend/src/app/app.actions.ts | 2 +- apps/frontend/src/app/app.module.ts | 2 + apps/frontend/src/app/app.reducer.ts | 22 +++++- .../scene-viewer-container/grid.service.ts | 7 +- .../scene-viewer-container.actions.ts | 2 +- .../scene-viewer-container.component.spec.ts | 3 +- .../scene-viewer-container.component.ts | 8 +- .../scene-viewer-container.effects.ts | 2 +- .../src/app/undo-redo/undo-redo.actions.ts | 21 +++++ .../src/app/undo-redo/undo-redo.effects.ts | 58 ++++++++++++++ .../src/app/undo-redo/undo-redo.module.ts | 8 ++ .../src/app/undo-redo/undo-redo.reducer.ts | 76 +++++++++++++++++++ .../scene-viewer/scene-viewer.component.ts | 16 +++- .../lib/scene-viewer/scene-viewer.service.ts | 52 +++++++------ libs/vdb/src/lib/tools/node-to-mesh.spec.ts | 9 ++- libs/vdb/src/lib/tools/node-to-mesh.ts | 2 - libs/vdb/src/lib/tree/root-node.ts | 10 ++- tsconfig.json | 21 ++--- 19 files changed, 269 insertions(+), 56 deletions(-) create mode 100644 apps/frontend/src/app/undo-redo/undo-redo.actions.ts create mode 100644 apps/frontend/src/app/undo-redo/undo-redo.effects.ts create mode 100644 apps/frontend/src/app/undo-redo/undo-redo.module.ts create mode 100644 apps/frontend/src/app/undo-redo/undo-redo.reducer.ts diff --git a/apps/benchmark/src/main.ts b/apps/benchmark/src/main.ts index 10319c92..d6bb2c68 100644 --- a/apps/benchmark/src/main.ts +++ b/apps/benchmark/src/main.ts @@ -86,7 +86,9 @@ function convertToTestSuite(suiteName: string, currentSuite: Benchmark.Suite): T } function sumUpTotalTime(): void { - report.time = report.suites.map(s => s.time).reduce((previous, current) => previous + current, 0); + report.time = report.suites + .map(s => s.time) + .reduce((previous, current) => (previous && current ? previous + current : 0), 0); } function everySuiteFinished(): boolean { diff --git a/apps/frontend/src/app/app.actions.ts b/apps/frontend/src/app/app.actions.ts index ab592e7e..d2d34e5c 100644 --- a/apps/frontend/src/app/app.actions.ts +++ b/apps/frontend/src/app/app.actions.ts @@ -1,6 +1,6 @@ import { createAction } from '@ngrx/store'; -const actionTypePrefix = '[App]'; +const actionTypePrefix = '[app]'; export const wentOnline = createAction(`${actionTypePrefix} Went online`); export const wentOffline = createAction(`${actionTypePrefix} Went offline`); diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts index 58db50bd..00108552 100644 --- a/apps/frontend/src/app/app.module.ts +++ b/apps/frontend/src/app/app.module.ts @@ -10,6 +10,7 @@ import { AppEffects } from './app.effects'; import { metaReducers, ROOT_REDUCERS } from './app.reducer'; import { SceneViewerContainerModule } from './scene-viewer-container'; import { ToolsPanelModule } from './tools-panel/tools-panel.module'; +import { UndoRedoModule } from './undo-redo/undo-redo.module'; @NgModule({ declarations: [AppComponent], @@ -38,6 +39,7 @@ import { ToolsPanelModule } from './tools-panel/tools-panel.module'; SceneViewerContainerModule, SidenavShellModule, ToolsPanelModule, + UndoRedoModule, ], providers: [], bootstrap: [AppComponent], diff --git a/apps/frontend/src/app/app.reducer.ts b/apps/frontend/src/app/app.reducer.ts index 82ec8af7..c100b744 100644 --- a/apps/frontend/src/app/app.reducer.ts +++ b/apps/frontend/src/app/app.reducer.ts @@ -10,8 +10,10 @@ import { import { environment } from '../environments/environment'; import * as fromSceneViewerContainer from './scene-viewer-container/scene-viewer-container.reducer'; import * as fromToolsPanel from './tools-panel/tools-panel.reducer'; +import * as fromUndoRedo from './undo-redo/undo-redo.reducer'; export interface State { + [fromUndoRedo.featureKey]: fromUndoRedo.State; [fromToolsPanel.featureKey]: fromToolsPanel.State; [fromSceneViewerContainer.featureKey]: fromSceneViewerContainer.State; } @@ -27,8 +29,9 @@ export const ROOT_REDUCERS = new InjectionToken> 'Root reducers token', { factory: () => ({ - [fromToolsPanel.featureKey]: fromToolsPanel.reducer, [fromSceneViewerContainer.featureKey]: fromSceneViewerContainer.reducer, + [fromToolsPanel.featureKey]: fromToolsPanel.reducer, + [fromUndoRedo.featureKey]: fromUndoRedo.reducer, }), }, ); @@ -78,3 +81,20 @@ export const selectSelectedToolId = createSelector( selectToolsPanelState, fromToolsPanel.selectSelectedToolId, ); + +/** + * UndoRedo reducers + */ +export const selectUndoRedoState = createFeatureSelector( + fromUndoRedo.featureKey, +); + +export const selectCurrentUndoAction = createSelector( + selectUndoRedoState, + fromUndoRedo.selectCurrentUndoAction, +); + +export const selectCurrentRedoAction = createSelector( + selectUndoRedoState, + fromUndoRedo.selectCurrentRedoAction, +); diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index 9197d9e7..8e2ff485 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -49,9 +49,10 @@ export class GridService { computeInternalNode1Mesh(origin: Coord): MeshData | undefined { const internal1 = this.accessor.probeInternalNode1(origin); - const mesh = nodeToMesh(internal1); - mesh.origin = internal1.origin; + if (!internal1) { + return undefined; + } - return mesh; + return nodeToMesh(internal1); } } diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts index 1651f716..3f2833a2 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -1,7 +1,7 @@ import { createAction, props } from '@ngrx/store'; import { Coord } from '@talus/vdb'; -const actionTypePrefix = '[SceneViewerContainer]'; +const actionTypePrefix = `[sceneViewerContainer]`; export const addVoxel = createAction( `${actionTypePrefix} Add voxel`, diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index cc914e18..81227396 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -66,7 +66,8 @@ describe('SceneViewerContainerComponent', () => { normal: [0, 0, 0], }); - expect(mockStore.dispatch).not.toHaveBeenCalled(); + // Only once called due to first initial added voxel at [0, 0, 0] + expect(mockStore.dispatch).toHaveBeenCalledTimes(1); }); it.each([ diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index d9efee4c..2abe4572 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; // import '@babylonjs/core/Rendering/edgesRenderer'; // import '@babylonjs/core/Rendering/outlineRenderer'; import { select, Store } from '@ngrx/store'; @@ -19,7 +19,7 @@ import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SceneViewerContainerComponent { +export class SceneViewerContainerComponent implements AfterViewInit { @ViewChild(SceneViewerComponent, { static: false }) private sceneViewerComponent: SceneViewerComponent; @@ -28,6 +28,10 @@ export class SceneViewerContainerComponent { constructor(private store: Store) {} + ngAfterViewInit(): void { + this.store.dispatch(addVoxel({ position: [0, 0, 0], value: 42 })); + } + onPointerPick(event: PointerPickInfo, selectedToolId: Tool): void { this.dispatchPickAction(event, selectedToolId); } diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts index fda8cc88..a9eab0b4 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts @@ -59,7 +59,7 @@ export class SceneViewerContainerEffects { next: ({ affectedOrigins }) => { affectedOrigins.map(origin => { const mesh = this.gridService.computeInternalNode1Mesh(origin); - this.sceneViewerService.updateNodeMesh(mesh); + this.sceneViewerService.updateNodeMesh(mesh, origin); }); }, }), diff --git a/apps/frontend/src/app/undo-redo/undo-redo.actions.ts b/apps/frontend/src/app/undo-redo/undo-redo.actions.ts new file mode 100644 index 00000000..c1bf041d --- /dev/null +++ b/apps/frontend/src/app/undo-redo/undo-redo.actions.ts @@ -0,0 +1,21 @@ +import { Action, createAction, props } from '@ngrx/store'; + +const actionTypePrefix = `[undoRedo]`; + +export const addUndo = createAction( + `${actionTypePrefix} Add undo`, + props<{ redoAction: Action; undoAction: Action }>(), +); + +export const undo = createAction(`${actionTypePrefix} Undo`); + +export const undone = createAction(`${actionTypePrefix} Undone`); + +export const addRedo = createAction( + `${actionTypePrefix} Add redo`, + props<{ redoAction: Action }>(), +); + +export const redo = createAction(`${actionTypePrefix} Redo`); + +export const redone = createAction(`${actionTypePrefix} Redone`); diff --git a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts new file mode 100644 index 00000000..be660702 --- /dev/null +++ b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts @@ -0,0 +1,58 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { Action, select, Store } from '@ngrx/store'; +import { filter, map, switchMap, withLatestFrom } from 'rxjs/operators'; +import * as fromApp from '../app.reducer'; +import { addVoxel, removeVoxel } from '../scene-viewer-container/scene-viewer-container.actions'; +import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; + +@Injectable() +export class UndoRedoEffects { + constructor(private actions$: Actions, private store: Store) {} + + undo$ = createEffect(() => + this.actions$.pipe( + ofType(undo), + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoAction))), + switchMap(([action, currentUndoAction]) => + currentUndoAction ? [currentUndoAction, undone()] : [undone()], + ), + ), + ); + + redo$ = createEffect(() => + this.actions$.pipe( + ofType(redo), + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoAction))), + switchMap(([action, currentRedoAction]) => + currentRedoAction ? [currentRedoAction, redone()] : [redone()], + ), + ), + ); + + userTriggeredActions$ = this.actions$.pipe( + withLatestFrom(this.store.pipe(select(fromApp.selectUndoRedoState))), + filter(([action, state]) => !state.isUndoRedoing), + map(([action, state]) => action), + ); + + addUndoActionForAddVoxel$ = createEffect(() => + this.userTriggeredActions$.pipe( + ofType(addVoxel), + map(action => [action, removeVoxel({ position: action.position })]), + map(this.createAddUndo), + ), + ); + + addUndoActionForRemoveVoxel$ = createEffect(() => + this.userTriggeredActions$.pipe( + ofType(removeVoxel), + map(action => [action, addVoxel({ position: action.position, value: 42 })]), + map(this.createAddUndo), + ), + ); + + createAddUndo([redoAction, undoAction]: Action[]): Action { + return addUndo({ redoAction, undoAction }); + } +} diff --git a/apps/frontend/src/app/undo-redo/undo-redo.module.ts b/apps/frontend/src/app/undo-redo/undo-redo.module.ts new file mode 100644 index 00000000..7dd160d4 --- /dev/null +++ b/apps/frontend/src/app/undo-redo/undo-redo.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core'; +import { EffectsModule } from '@ngrx/effects'; +import { UndoRedoEffects } from './undo-redo.effects'; + +@NgModule({ + imports: [EffectsModule.forFeature([UndoRedoEffects])], +}) +export class UndoRedoModule {} diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts new file mode 100644 index 00000000..5b717a4e --- /dev/null +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts @@ -0,0 +1,76 @@ +import { Action, createReducer, on } from '@ngrx/store'; +import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; + +/** + * Use normal reducer instead of meta-reducer, to have the state in the normal store + * and therefore accessible (e.g. for display in app the number of redo actions). + * Also use normal effects to run/replay/dispatch the action to be undone. + */ + +export const featureKey = 'undoRedo'; + +export interface State { + currentIndex: number; + isUndoRedoing: boolean; + redoActions: Action[]; + undoActions: Action[]; +} + +export const initialState: State = { + currentIndex: -1, + isUndoRedoing: false, + redoActions: [], + undoActions: [], +}; + +const maxBufferSize = 10; +const maxBufferIndex = maxBufferSize - 1; + +export const reducer = createReducer( + initialState, + + on(addUndo, (state, { redoAction, undoAction }) => { + const newIndex = state.currentIndex + 1; + + const redoActions = state.redoActions.slice(0, newIndex); + const undoActions = state.undoActions.slice(0, newIndex); + + return { + ...state, + currentIndex: newIndex > maxBufferIndex ? maxBufferIndex : newIndex, + redoActions: [...redoActions.slice(-maxBufferIndex), redoAction], + undoActions: [...undoActions.slice(-maxBufferIndex), undoAction], + }; + }), + + on(undo, redo, state => { + return { + ...state, + isUndoRedoing: true, + }; + }), + + on(undone, state => { + const newIndex = state.currentIndex - 1; + + return { + ...state, + isUndoRedoing: false, + currentIndex: newIndex < 0 ? -1 : newIndex, + }; + }), + + on(redone, state => { + const newIndex = state.currentIndex + 1; + const maxRedoIndex = state.redoActions.length - 1; + + return { + ...state, + isUndoRedoing: false, + currentIndex: newIndex > maxRedoIndex ? maxRedoIndex : newIndex, + }; + }), +); + +export const selectCurrentUndoAction = (state: State) => state.undoActions[state.currentIndex]; +export const selectCurrentRedoAction = (state: State) => state.redoActions[state.currentIndex + 1]; diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts index 5d363801..7363c467 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts @@ -51,7 +51,7 @@ export class SceneViewerComponent implements OnInit { // Source: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop private getFiles(event: DragEvent): File[] { - return event.dataTransfer.items + return event.dataTransfer && event.dataTransfer.items ? this.getFilesFromDataTransferItemList(event) : this.getFilesFromDataTransfer(event); } @@ -59,11 +59,19 @@ export class SceneViewerComponent implements OnInit { private getFilesFromDataTransferItemList(event: DragEvent): File[] { const files: File[] = []; + if (!event.dataTransfer) { + return files; + } + // Use DataTransferItemList interface to access the file(s) for (let i = 0; i < event.dataTransfer.items.length; i++) { // If dropped items aren't files, reject them if (event.dataTransfer.items[i].kind === 'file') { - files.push(event.dataTransfer.items[i].getAsFile()); + const file = event.dataTransfer.items[i].getAsFile(); + + if (file) { + files.push(file); + } } } @@ -73,6 +81,10 @@ export class SceneViewerComponent implements OnInit { private getFilesFromDataTransfer(event: DragEvent): File[] { const files: File[] = []; + if (!event.dataTransfer) { + return files; + } + // Use DataTransfer interface to access the file(s) for (let i = 0; i < event.dataTransfer.files.length; i++) { files.push(event.dataTransfer.files[i]); diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 451bfbc2..cf4d42fd 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -1,4 +1,5 @@ import { Injectable } from '@angular/core'; +import { AbstractMesh } from '@babylonjs/core'; // Babylon.js needs to target individual files to fully benefit from tree shaking. // See: https://doc.babylonjs.com/features/es6_support#tree-shaking import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera'; @@ -10,7 +11,6 @@ import { Vector3 } from '@babylonjs/core/Maths/math.vector'; import { VertexBuffer } from '@babylonjs/core/Meshes/buffer'; import { Mesh } from '@babylonjs/core/Meshes/mesh'; import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData'; -import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder'; import { TransformNode } from '@babylonjs/core/Meshes/transformNode'; import '@babylonjs/core/Physics/physicsHelper'; // Needed for `onPointerPick` import { Scene } from '@babylonjs/core/scene'; @@ -71,11 +71,6 @@ export class SceneViewerService { this.createLight(); this.registerPointerPick(); - - const box = MeshBuilder.CreateBox('box', {}, this.scene); - box.position.x = 0.5; - box.position.y = 0.5; - box.position.z = 0.5; } startRendering(): void { @@ -86,8 +81,8 @@ export class SceneViewerService { this.engine.resize(); } - updateNodeMesh(mesh?: MeshData): void { - const meshName = `node1 [${mesh.origin}]`; + updateNodeMesh(mesh: MeshData | undefined, origin: Coord): void { + const meshName = `node1 [${origin}]`; this.deleteMesh(meshName); @@ -140,7 +135,10 @@ export class SceneViewerService { camera.angularSensibilityX = 200; camera.angularSensibilityY = 100; - camera.attachControl(this.engine.getRenderingCanvas(), true, false, 2); + const renderingCanvas = this.engine.getRenderingCanvas(); + if (renderingCanvas) { + camera.attachControl(renderingCanvas, true, false, 2); + } camera.setPosition(new Vector3(20, 20, -20)); } @@ -150,30 +148,34 @@ export class SceneViewerService { private registerPointerPick(): void { this.scene.onPointerPick = (event: PointerEvent, pickInfo: PickingInfo): void => { - const info: PointerPickInfo = { - pickedPoint: vector3ToCoord(pickInfo.pickedPoint), - pointerButton: event.button, - normal: this.getNormal(pickInfo), - }; - - this.pointerPick$.next(info); + if (pickInfo.pickedMesh && pickInfo.pickedPoint) { + const info: PointerPickInfo = { + pickedPoint: vector3ToCoord(pickInfo.pickedPoint), + pointerButton: event.button, + normal: this.getNormal(pickInfo.pickedMesh, pickInfo.faceId), + }; + + this.pointerPick$.next(info); + } }; } /** * PickingInfo.getNormal() requires to have indices which are not available - * for an unindexed custom mesh. Therefore, read normals directly from picked mesh. + * for an un-indexed custom mesh. Therefore, read normals directly from picked mesh. * * https://github.com/BabylonJS/Babylon.js/blob/master/src/Collisions/pickingInfo.ts#L65 */ - private getNormal(pickInfo: PickingInfo): Coord { - const normals = pickInfo.pickedMesh.getVerticesData(VertexBuffer.NormalKind); - - return [ - normals[pickInfo.faceId * 9], - normals[pickInfo.faceId * 9 + 1], - normals[pickInfo.faceId * 9 + 2], - ]; + private getNormal(pickedMesh: AbstractMesh, faceId: number): Coord { + const normals = pickedMesh.getVerticesData(VertexBuffer.NormalKind); + + if (!normals) { + throw new Error('Could not get normals from picked mesh.'); + } + + const faceIndex = faceId * 9; + + return [normals[faceIndex], normals[faceIndex + 1], normals[faceIndex + 2]]; } private deleteMesh(name: string): void { diff --git a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts index 60cdd34e..a221ae6c 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts @@ -19,8 +19,11 @@ describe('nodeToMesh()', () => { const xyz = 3; const rgba = 4; - expect(meshData.positions.length).toEqual(voxels * triangleCorners * xyz); - expect(meshData.colors.length).toEqual(voxels * triangleCorners * rgba); - expect(meshData.normals.length).toEqual(meshData.positions.length); + expect(meshData).toBeDefined(); + if (meshData) { + expect(meshData.positions.length).toEqual(voxels * triangleCorners * xyz); + expect(meshData.colors.length).toEqual(voxels * triangleCorners * rgba); + expect(meshData.normals.length).toEqual(meshData.positions.length); + } }); }); diff --git a/libs/vdb/src/lib/tools/node-to-mesh.ts b/libs/vdb/src/lib/tools/node-to-mesh.ts index f3d73b8f..321478fb 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.ts @@ -14,13 +14,11 @@ * 0--- X 0-------1 */ -import { Coord } from '../math'; import { HashableNode } from '../tree/node'; export interface MeshData { colors: number[]; normals: number[]; - origin?: Coord; positions: number[]; } diff --git a/libs/vdb/src/lib/tree/root-node.ts b/libs/vdb/src/lib/tree/root-node.ts index caabf4b5..d26b7bde 100644 --- a/libs/vdb/src/lib/tree/root-node.ts +++ b/libs/vdb/src/lib/tree/root-node.ts @@ -74,8 +74,8 @@ export class RootNode implements HashableNode { } setValueOn(xyz: Coord, value: T): void { + let child: HashableNode | undefined; const struct = this.findCoord(xyz); - let child: HashableNode; if (!struct) { child = new InternalNode2(xyz, this._background); @@ -93,7 +93,7 @@ export class RootNode implements HashableNode { } setValueAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void { - let child: HashableNode; + let child: HashableNode | undefined; const struct = this.findCoord(xyz); if (!struct) { @@ -113,7 +113,7 @@ export class RootNode implements HashableNode { } setValueOffAndCache(xyz: Coord, value: T, accessor: ValueAccessor3): void { - let child: HashableNode; + let child: HashableNode | undefined; const struct = this.findCoord(xyz); if (!struct) { @@ -202,6 +202,10 @@ class NodeStruct { constructor(private child?: HashableNode) {} getChild(): HashableNode { + if (!this.child) { + throw new Error('Access undefined child.'); + } + return this.child; } diff --git a/tsconfig.json b/tsconfig.json index 79137cd9..5139f576 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,27 @@ { "compileOnSave": false, "compilerOptions": { - "rootDir": ".", - "sourceMap": true, + "baseUrl": ".", "declaration": false, - "moduleResolution": "node", "emitDecoratorMetadata": true, "esModuleInterop": true, "experimentalDecorators": true, "importHelpers": true, - "target": "es2015", - "module": "esnext", - "typeRoots": ["node_modules/@types"], "lib": ["es2017", "dom"], - "skipLibCheck": true, - "skipDefaultLibCheck": true, - "baseUrl": ".", + "module": "esnext", + "moduleResolution": "node", "paths": { "@talus/ui": ["libs/ui/src/index.ts"], "@talus/math": ["libs/math/src/index.ts"], "@talus/vdb": ["libs/vdb/src/index.ts"] - } + }, + "rootDir": ".", + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "sourceMap": true, + "strictNullChecks": true, + "target": "es2015", + "typeRoots": ["node_modules/@types"] }, "exclude": ["node_modules", "tmp"] } From 700ff89aa65ffae75b252ddae42d6f9e23ff9a87 Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Tue, 14 Jan 2020 08:09:33 +0100 Subject: [PATCH 42/67] feat(frontend): set active state of voxel, return color when deleting (#11) --- .../scene-viewer-container/grid.service.ts | 2 +- libs/vdb/src/lib/tree/internal-node.ts | 21 ++++++++++++++++ libs/vdb/src/lib/tree/leaf-node.ts | 15 ++++++++++++ libs/vdb/src/lib/tree/node.ts | 8 +++++++ libs/vdb/src/lib/tree/root-node.ts | 24 +++++++++++++++++++ libs/vdb/src/lib/tree/value-accessor.spec.ts | 21 ++++++++++++++++ libs/vdb/src/lib/tree/value-accessor.ts | 14 +++++++++++ libs/vdb/src/lib/util/node-mask.ts | 4 ++++ 8 files changed, 108 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index 8e2ff485..83e49344 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -41,7 +41,7 @@ export class GridService { } removeVoxel(xyz: Coord): Coord { - this.accessor.setValueOff(xyz, this.grid.background); + this.accessor.setActiveState(xyz, false); return this.accessor.internalNode1Origin; } diff --git a/libs/vdb/src/lib/tree/internal-node.ts b/libs/vdb/src/lib/tree/internal-node.ts index b877927e..072d7e9c 100644 --- a/libs/vdb/src/lib/tree/internal-node.ts +++ b/libs/vdb/src/lib/tree/internal-node.ts @@ -163,6 +163,27 @@ abstract class InternalNode implements HashableNode { } } + setActiveStateAndCache(xyz: Coord, on: boolean, accessor: ValueAccessor3): void { + const i: Index = this.coordToOffset(xyz); + const node = this.nodes[i]; + let hasChild = this.childMask.isOn(i); + + if (!hasChild) { + if (on !== this.valueMask.isOn(i)) { + // If the voxel belongs to a tile with the wrong active state, + // then a child subtree must be constructed. + // 'on' is the voxel's new state, therefore '!on' is the tile's current state + hasChild = true; + this.setChildNode(i, this.createChildNode(xyz, node.getValue(), !on)); + } + } + + if (hasChild) { + accessor.insert(xyz, node.getChild()); + node.getChild().setActiveStateAndCache(xyz, on, accessor); + } + } + isValueOn(xyz: Coord): boolean { const i: Index = this.coordToOffset(xyz); if (this.childMask.isOff(i)) { diff --git a/libs/vdb/src/lib/tree/leaf-node.ts b/libs/vdb/src/lib/tree/leaf-node.ts index 6fbed000..b7d9b10d 100644 --- a/libs/vdb/src/lib/tree/leaf-node.ts +++ b/libs/vdb/src/lib/tree/leaf-node.ts @@ -98,6 +98,13 @@ export class LeafNode implements HashableNode { this.valueMask.setOff(offset); } + /** + * Set the active state of the voxel at the given coordinates but don't change its value. + */ + setActiveState(xyz: Coord, on: boolean): void { + this.valueMask.set(LeafNode.coordToOffset(xyz), on); + } + /** * Return the value of the voxel at the given coordinates. */ @@ -149,6 +156,14 @@ export class LeafNode implements HashableNode { return this.isValueOn(xyz); } + /** + * @brief Set the active state of the voxel at the given coordinates without changing its value. + * @note Used internally by ValueAccessor. + */ + setActiveStateAndCache(xyz: Coord, on: boolean, _: ValueAccessor3): void { + return this.setActiveState(xyz, on); + } + /** * Return the global coordinates for a linear table offset. */ diff --git a/libs/vdb/src/lib/tree/node.ts b/libs/vdb/src/lib/tree/node.ts index a4fff5bb..01d4c8cc 100644 --- a/libs/vdb/src/lib/tree/node.ts +++ b/libs/vdb/src/lib/tree/node.ts @@ -64,6 +64,14 @@ export interface HashableNode extends Node { * @note Used internally by ValueAccessor. */ isValueOnAndCache(xyz: Coord, accessor: ValueAccessor3): boolean; + + /** + * Set the active state of the voxel at the given coordinates without changing its value. + * If necessary, update the accessor with pointers to the nodes along the path + * from the root node to the node containing the voxel. + * @note Used internally by ValueAccessor. + */ + setActiveStateAndCache(xyz: Coord, on: boolean, accessor: ValueAccessor3): void; } export interface IterableNode { diff --git a/libs/vdb/src/lib/tree/root-node.ts b/libs/vdb/src/lib/tree/root-node.ts index d26b7bde..8366e667 100644 --- a/libs/vdb/src/lib/tree/root-node.ts +++ b/libs/vdb/src/lib/tree/root-node.ts @@ -134,6 +134,30 @@ export class RootNode implements HashableNode { } } + setActiveStateAndCache(xyz: Coord, on: boolean, accessor: ValueAccessor3): void { + let child: HashableNode | undefined; + const struct = this.findCoord(xyz); + + if (!struct) { + if (on) { + child = new InternalNode2(xyz, this._background); + this.table.set(RootNode.coordToKey(xyz), new NodeStruct(child)); + } /*else { + // Nothing to do; (x, y, z) is background and therefore already inactive. + }*/ + } else if (struct.isChild()) { + child = struct.getChild(); + } else if (on !== struct.getTile().active) { + child = new InternalNode2(xyz, struct.getTile().value, !on); + struct.setChild(child); + } + + if (child) { + accessor.insert(xyz, child); + child.setActiveStateAndCache(xyz, on, accessor); + } + } + isValueOn(xyz: Coord): boolean { const struct = this.findCoord(xyz); diff --git a/libs/vdb/src/lib/tree/value-accessor.spec.ts b/libs/vdb/src/lib/tree/value-accessor.spec.ts index 425daade..d110c44e 100644 --- a/libs/vdb/src/lib/tree/value-accessor.spec.ts +++ b/libs/vdb/src/lib/tree/value-accessor.spec.ts @@ -64,6 +64,27 @@ describe('ValueAccessor', () => { }); }); + describe('setActiveState()', () => { + it('should set state', () => { + const tree = new Tree(0); + const accessor = new ValueAccessor3(tree); + + accessor.setValueOn([0, 0, 0], 1496); + expect(accessor.getValue([0, 0, 0])).toEqual(1496); + expect(accessor.isValueOn([0, 0, 0])).toEqual(true); + + accessor.setActiveState([0, 0, 0], false); + expect(accessor.getValue([0, 0, 0])).toEqual(1496); + expect(accessor.isValueOn([0, 0, 0])).toBeFalsy(); + + accessor.setActiveState([0, 0, 0], true); + expect(accessor.getValue([0, 0, 0])).toEqual(1496); + expect(accessor.isValueOn([0, 0, 0])).toBeTruthy(); + + expect(accessor.isCached([0, 0, 0])).toBeTruthy(); + }); + }); + describe('isValueOn()', () => { it('should set value and (de)activate voxel', () => { const tree = new Tree(0); diff --git a/libs/vdb/src/lib/tree/value-accessor.ts b/libs/vdb/src/lib/tree/value-accessor.ts index 4b881ff4..d2d54fa0 100644 --- a/libs/vdb/src/lib/tree/value-accessor.ts +++ b/libs/vdb/src/lib/tree/value-accessor.ts @@ -126,6 +126,20 @@ export class ValueAccessor3 { return this.tree.root.isValueOnAndCache(xyz, this); } + /** + * Set the active state of the voxel at the given coordinates without changing its value. + */ + setActiveState(xyz: Coord, on: boolean): void { + if (this.isHashed0(xyz)) { + this.leafNode.setActiveStateAndCache(xyz, on, this); + } else if (this.isHashed1(xyz)) { + this.internalNode1.setActiveStateAndCache(xyz, on, this); + } else if (this.isHashed2(xyz)) { + this.internalNode2.setActiveStateAndCache(xyz, on, this); + } + this.tree.root.setActiveStateAndCache(xyz, on, this); + } + // tslint:disable:no-bitwise insert(xyz: Coord, node: HashableNode): void { if (node instanceof LeafNode) { diff --git a/libs/vdb/src/lib/util/node-mask.ts b/libs/vdb/src/lib/util/node-mask.ts index a654a154..5c45e9a8 100644 --- a/libs/vdb/src/lib/util/node-mask.ts +++ b/libs/vdb/src/lib/util/node-mask.ts @@ -51,4 +51,8 @@ export class NodeMask { isOff(i: Index): boolean { return this.mask.test(i) === false; } + + set(i: Index, on: boolean): void { + on ? this.setOn(i) : this.setOff(i); + } } From 4b355762fa659818140d539ef1a8aeb2f7d407c0 Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Wed, 15 Jan 2020 10:19:15 +0100 Subject: [PATCH 43/67] feat(ui/frontend): add menu-bar (#12) * feat(frontend): add menu-bar * feat(frontend): add menu-bar-container * test(frontend): inject mock store for menu-bar-container * refactor(frontend): add missing `menu-bar.component` * test(frontend): import `MenuBarModule` --- apps/frontend/src/app/app.component.scss | 11 +++++ apps/frontend/src/app/app.component.spec.ts | 14 +++++- apps/frontend/src/app/app.component.ts | 31 +++++++----- apps/frontend/src/app/app.module.ts | 2 + .../menu-bar-container.actions.ts | 6 +++ .../menu-bar-container.component.spec.ts | 42 ++++++++++++++++ .../menu-bar-container.component.ts | 40 ++++++++++++++++ .../menu-bar-container.module.ts | 10 ++++ .../app/tools-panel/tools-panel.actions.ts | 2 +- .../src/app/undo-redo/undo-redo.effects.ts | 5 +- .../src/app/undo-redo/undo-redo.reducer.ts | 3 +- libs/ui/src/index.ts | 5 +- libs/ui/src/lib/menu-bar/index.ts | 2 + .../src/lib/menu-bar/menu-bar.component.scss | 5 ++ .../lib/menu-bar/menu-bar.component.spec.ts | 24 ++++++++++ .../ui/src/lib/menu-bar/menu-bar.component.ts | 48 +++++++++++++++++++ libs/ui/src/lib/menu-bar/menu-bar.module.ts | 11 +++++ .../scene-viewer/scene-viewer.component.scss | 4 +- .../sidenav-shell.component.scss | 1 - 19 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 apps/frontend/src/app/app.component.scss create mode 100644 apps/frontend/src/app/menu-bar-container/menu-bar-container.actions.ts create mode 100644 apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts create mode 100644 apps/frontend/src/app/menu-bar-container/menu-bar-container.component.ts create mode 100644 apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts create mode 100644 libs/ui/src/lib/menu-bar/index.ts create mode 100644 libs/ui/src/lib/menu-bar/menu-bar.component.scss create mode 100644 libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts create mode 100644 libs/ui/src/lib/menu-bar/menu-bar.component.ts create mode 100644 libs/ui/src/lib/menu-bar/menu-bar.module.ts diff --git a/apps/frontend/src/app/app.component.scss b/apps/frontend/src/app/app.component.scss new file mode 100644 index 00000000..f2cbf979 --- /dev/null +++ b/apps/frontend/src/app/app.component.scss @@ -0,0 +1,11 @@ +:host { + display: flex; + flex-flow: column; + height: 100%; +} + +main { + flex-grow: 1; + // https://stackoverflow.com/a/38383437 + min-height: 0; +} diff --git a/apps/frontend/src/app/app.component.spec.ts b/apps/frontend/src/app/app.component.spec.ts index 4605e2a5..20f333bc 100644 --- a/apps/frontend/src/app/app.component.spec.ts +++ b/apps/frontend/src/app/app.component.spec.ts @@ -5,6 +5,13 @@ import { RouterTestingModule } from '@angular/router/testing'; import { SceneViewerTestModule, SidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; +@Component({ + selector: 'fe-menu-bar-container', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +class MenuBarContainerStubComponent {} + @Component({ selector: 'fe-scene-viewer-container', template: '', @@ -22,7 +29,12 @@ class ToolsPanelStubComponent {} describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [AppComponent, SceneViewerContainerStubComponent, ToolsPanelStubComponent], + declarations: [ + AppComponent, + MenuBarContainerStubComponent, + SceneViewerContainerStubComponent, + ToolsPanelStubComponent, + ], imports: [ BrowserAnimationsModule, RouterTestingModule, diff --git a/apps/frontend/src/app/app.component.ts b/apps/frontend/src/app/app.component.ts index a5ef2d16..26ac5b17 100644 --- a/apps/frontend/src/app/app.component.ts +++ b/apps/frontend/src/app/app.component.ts @@ -3,21 +3,30 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'fe-root', template: ` - - - - +
+ +
- - Right - +
+ + + + - - - - + + Right + + + + + + +
+ + `, changeDetection: ChangeDetectionStrategy.OnPush, + styleUrls: ['./app.component.scss'], }) export class AppComponent { title = 'frontend'; diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts index 00108552..67ca1a26 100644 --- a/apps/frontend/src/app/app.module.ts +++ b/apps/frontend/src/app/app.module.ts @@ -8,6 +8,7 @@ import { SidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; import { AppEffects } from './app.effects'; import { metaReducers, ROOT_REDUCERS } from './app.reducer'; +import { MenuBarContainerModule } from './menu-bar-container/menu-bar-container.module'; import { SceneViewerContainerModule } from './scene-viewer-container'; import { ToolsPanelModule } from './tools-panel/tools-panel.module'; import { UndoRedoModule } from './undo-redo/undo-redo.module'; @@ -36,6 +37,7 @@ import { UndoRedoModule } from './undo-redo/undo-redo.module'; }, }), + MenuBarContainerModule, SceneViewerContainerModule, SidenavShellModule, ToolsPanelModule, diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.actions.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.actions.ts new file mode 100644 index 00000000..04d964a2 --- /dev/null +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.actions.ts @@ -0,0 +1,6 @@ +import { createAction } from '@ngrx/store'; + +const actionTypePrefix = `[menuBarContainer]`; + +export const undo = createAction(`${actionTypePrefix} Undo`); +export const redo = createAction(`${actionTypePrefix} Redo`); diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts new file mode 100644 index 00000000..d4ec9c9e --- /dev/null +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts @@ -0,0 +1,42 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { MockStore } from '@ngrx/store/testing'; +import { ROOT_REDUCERS, State } from '../app.reducer'; +import { MenuBarContainerComponent } from './menu-bar-container.component'; +import { MenuBarContainerModule } from './menu-bar-container.module'; + +describe('MenuBarComponent', () => { + let component: MenuBarContainerComponent; + let fixture: ComponentFixture; + + let store: MockStore; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [], + imports: [ + MenuBarContainerModule, + StoreModule.forRoot(ROOT_REDUCERS, { + runtimeChecks: { + strictStateImmutability: true, + strictActionImmutability: true, + strictStateSerializability: true, + strictActionSerializability: true, + }, + }), + ], + }).compileComponents(); + + store = TestBed.get>(Store); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MenuBarContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.ts new file mode 100644 index 00000000..a2e76188 --- /dev/null +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.ts @@ -0,0 +1,40 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { Action, Store } from '@ngrx/store'; +import { UiMenuBarConfig } from '@talus/ui'; +import * as fromApp from '../app.reducer'; +import { redo, undo } from './menu-bar-container.actions'; + +@Component({ + selector: 'fe-menu-bar-container', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MenuBarContainerComponent { + menuConfig: UiMenuBarConfig = { + menus: [ + { + label: 'Edit', + menuItems: [ + { + icon: 'undo', + label: 'Undo', + value: undo(), + }, + { + icon: 'redo', + label: 'Redo', + value: redo(), + }, + ], + }, + ], + }; + + constructor(private store: Store) {} + + onMenuItemClick(action: Action): void { + this.store.dispatch(action); + } +} diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts new file mode 100644 index 00000000..b8d0c534 --- /dev/null +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { MenuBarModule } from '@talus/ui'; +import { MenuBarContainerComponent } from './menu-bar-container.component'; + +@NgModule({ + declarations: [MenuBarContainerComponent], + imports: [MenuBarModule], + exports: [MenuBarContainerComponent], +}) +export class MenuBarContainerModule {} diff --git a/apps/frontend/src/app/tools-panel/tools-panel.actions.ts b/apps/frontend/src/app/tools-panel/tools-panel.actions.ts index 308ce61b..1827a91b 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.actions.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.actions.ts @@ -1,4 +1,4 @@ import { createAction, props } from '@ngrx/store'; import { Tool } from './tool.model'; -export const selectTool = createAction('[ToolsPanel] Select tool', props<{ id: Tool }>()); +export const selectTool = createAction('[toolsPanel] Select tool', props<{ id: Tool }>()); diff --git a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts index be660702..65d2a52c 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts @@ -3,6 +3,7 @@ import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Action, select, Store } from '@ngrx/store'; import { filter, map, switchMap, withLatestFrom } from 'rxjs/operators'; import * as fromApp from '../app.reducer'; +import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions'; import { addVoxel, removeVoxel } from '../scene-viewer-container/scene-viewer-container.actions'; import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; @@ -12,7 +13,7 @@ export class UndoRedoEffects { undo$ = createEffect(() => this.actions$.pipe( - ofType(undo), + ofType(undo, menuBarContainerActions.undo), withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoAction))), switchMap(([action, currentUndoAction]) => currentUndoAction ? [currentUndoAction, undone()] : [undone()], @@ -22,7 +23,7 @@ export class UndoRedoEffects { redo$ = createEffect(() => this.actions$.pipe( - ofType(redo), + ofType(redo, menuBarContainerActions.redo), withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoAction))), switchMap(([action, currentRedoAction]) => currentRedoAction ? [currentRedoAction, redone()] : [redone()], diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts index 5b717a4e..ad36de14 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts @@ -1,4 +1,5 @@ import { Action, createReducer, on } from '@ngrx/store'; +import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions'; import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; /** @@ -43,7 +44,7 @@ export const reducer = createReducer( }; }), - on(undo, redo, state => { + on(undo, menuBarContainerActions.undo, redo, menuBarContainerActions.redo, state => { return { ...state, isUndoRedoing: true, diff --git a/libs/ui/src/index.ts b/libs/ui/src/index.ts index 03119d04..5793e9fa 100644 --- a/libs/ui/src/index.ts +++ b/libs/ui/src/index.ts @@ -1,4 +1,5 @@ -export * from './lib/ui.module'; -export * from './lib/sidenav-shell'; +export * from './lib/menu-bar'; export * from './lib/scene-viewer'; +export * from './lib/sidenav-shell'; export * from './lib/toolbar'; +export * from './lib/ui.module'; diff --git a/libs/ui/src/lib/menu-bar/index.ts b/libs/ui/src/lib/menu-bar/index.ts new file mode 100644 index 00000000..3a658a8f --- /dev/null +++ b/libs/ui/src/lib/menu-bar/index.ts @@ -0,0 +1,2 @@ +export * from './menu-bar.component'; +export * from './menu-bar.module'; diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.scss b/libs/ui/src/lib/menu-bar/menu-bar.component.scss new file mode 100644 index 00000000..22da7177 --- /dev/null +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.scss @@ -0,0 +1,5 @@ +$angular-button-height: 36px; + +mat-toolbar { + height: $angular-button-height; +} diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts new file mode 100644 index 00000000..1d7c4150 --- /dev/null +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { MenuBarComponent } from './menu-bar.component'; +import { MenuBarModule } from './menu-bar.module'; + +describe('MenuBarComponent', () => { + let component: MenuBarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [MenuBarModule], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MenuBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.ts new file mode 100644 index 00000000..35a0b300 --- /dev/null +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.ts @@ -0,0 +1,48 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; + +export interface UiMenuBarConfig { + menus: UiMenuBarMenu[]; +} + +interface UiMenuBarMenu { + label: string; + menuItems: UiMenuBarMenuItem[]; +} + +interface UiMenuBarMenuItem { + icon?: string; + label: string; + value: T; +} + +@Component({ + selector: 'ui-menu-bar', + template: ` + + + + + + + + + `, + styleUrls: ['./menu-bar.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MenuBarComponent { + @Input() menuConfig: UiMenuBarConfig = { menus: [] }; + + @Output() menuItemClick = new EventEmitter(); + + onMenuItemClick(value: any): void { + this.menuItemClick.emit(value); + } +} diff --git a/libs/ui/src/lib/menu-bar/menu-bar.module.ts b/libs/ui/src/lib/menu-bar/menu-bar.module.ts new file mode 100644 index 00000000..63616842 --- /dev/null +++ b/libs/ui/src/lib/menu-bar/menu-bar.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule } from '@angular/material'; +import { MenuBarComponent } from './menu-bar.component'; + +@NgModule({ + declarations: [MenuBarComponent], + imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule], + exports: [MenuBarComponent], +}) +export class MenuBarModule {} diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.scss b/libs/ui/src/lib/scene-viewer/scene-viewer.component.scss index 519ffd16..5a6bfab9 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.scss +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.scss @@ -1,6 +1,4 @@ -:host, canvas { - display: block; - width: 100%; height: 100%; + width: 100%; } diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.scss b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.scss index dbc3fea8..62b77cef 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.scss +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.scss @@ -1,6 +1,5 @@ :host, mat-sidenav-container { - display: block; height: 100%; } From 03395436c5bd2eee0e4fd99d617002b60bf6405a Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Wed, 15 Jan 2020 11:28:10 +0100 Subject: [PATCH 44/67] feat(frontend): undo/redo with start/end actions (#13) * feat(frontend): undo/redo with start/end actions * test(frontend): provide `valueToColor()` * feat(frontend): set random color when adding a voxel * test(frontend): add same color of voxel * refactor(frontend): use directly `props` * refactor(frontend): throw error when coord&values not same length --- apps/frontend/src/app/app.reducer.ts | 18 +++- .../scene-viewer-container/grid.service.ts | 60 ++++++++++---- .../scene-viewer-container.actions.ts | 13 +-- .../scene-viewer-container.component.spec.ts | 4 +- .../scene-viewer-container.component.ts | 2 +- .../scene-viewer-container.effects.ts | 38 ++++++--- .../src/app/undo-redo/undo-redo.actions.ts | 7 +- .../src/app/undo-redo/undo-redo.effects.ts | 80 ++++++++++++++---- .../src/app/undo-redo/undo-redo.reducer.ts | 66 ++++++++++----- libs/vdb/src/lib/tools/node-to-mesh.spec.ts | 2 +- libs/vdb/src/lib/tools/node-to-mesh.ts | 82 +++++++++---------- 11 files changed, 250 insertions(+), 122 deletions(-) diff --git a/apps/frontend/src/app/app.reducer.ts b/apps/frontend/src/app/app.reducer.ts index c100b744..4c401a18 100644 --- a/apps/frontend/src/app/app.reducer.ts +++ b/apps/frontend/src/app/app.reducer.ts @@ -89,12 +89,22 @@ export const selectUndoRedoState = createFeatureSelector(); + addVoxels(coords: Coord[], values: number[]): VoxelChange[] { + const changes = new Map(); if (coords.length !== values.length) { - coords.forEach(xyz => { - const affected = this.addVoxel(xyz, values[0]); - affectedOrigins.set(affected.toString(), affected); - }); - } else { - coords.forEach((xyz, i) => { - const affected = this.addVoxel(xyz, values[i]); - affectedOrigins.set(affected.toString(), affected); - }); + throw new Error(`Coordinates and values don't have the same length.`); } - return Array.from(affectedOrigins.values()); + coords.forEach((xyz, i) => { + const change = this.addVoxel(xyz, values[i]); + changes.set(change.affectedNodeOrigin.toString(), change); + }); + + return Array.from(changes.values()); } - removeVoxel(xyz: Coord): Coord { + removeVoxel(xyz: Coord): VoxelChange { this.accessor.setActiveState(xyz, false); - return this.accessor.internalNode1Origin; + return { + affectedNodeOrigin: this.accessor.internalNode1Origin, + value: this.accessor.getValue(xyz), + position: xyz, + }; } computeInternalNode1Mesh(origin: Coord): MeshData | undefined { @@ -53,6 +69,16 @@ export class GridService { return undefined; } - return nodeToMesh(internal1); + return nodeToMesh(internal1, this.valueToColor); } + + private valueToColor = (value: number): [number, number, number, number] => { + return this.colors[value % 8]; + }; +} + +export interface VoxelChange { + affectedNodeOrigin: Coord; + value: number; + position: Coord; } diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts index 3f2833a2..5154e280 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.actions.ts @@ -1,5 +1,6 @@ import { createAction, props } from '@ngrx/store'; import { Coord } from '@talus/vdb'; +import { VoxelChange } from './grid.service'; const actionTypePrefix = `[sceneViewerContainer]`; @@ -8,10 +9,7 @@ export const addVoxel = createAction( props<{ position: Coord; value: number }>(), ); export const addVoxelFailed = createAction(`${actionTypePrefix} Add voxel failed`); -export const voxelAdded = createAction( - `${actionTypePrefix} Voxel added`, - props<{ affectedOrigins: Coord[] }>(), -); +export const voxelAdded = createAction(`${actionTypePrefix} Voxel added`, props()); export const addVoxels = createAction( `${actionTypePrefix} Add voxels`, @@ -20,7 +18,7 @@ export const addVoxels = createAction( export const addVoxelsFailed = createAction(`${actionTypePrefix} Add voxels failed`); export const voxelsAdded = createAction( `${actionTypePrefix} Voxels added`, - props<{ affectedOrigins: Coord[] }>(), + props<{ voxelChanges: VoxelChange[] }>(), ); export const removeVoxel = createAction( @@ -28,7 +26,4 @@ export const removeVoxel = createAction( props<{ position: Coord }>(), ); export const removeVoxelFailed = createAction(`${actionTypePrefix} Remove voxel failed`); -export const voxelRemoved = createAction( - `${actionTypePrefix} Voxel removed`, - props<{ affectedOrigins: Coord[] }>(), -); +export const voxelRemoved = createAction(`${actionTypePrefix} Voxel removed`, props()); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 81227396..931997cf 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -114,7 +114,8 @@ describe('SceneViewerContainerComponent', () => { ])( 'should dispatch `addVoxel` action for %j', (pickedPoint: Coord, position: Coord, normal: Coord) => { - const action = addVoxel({ position, value: 42 }); + const initialAction = addVoxel({ position: [0, 0, 0], value: 42 }); + const action = addVoxel({ position, value: 1 }); stubComponent.pointerPick.next({ pickedPoint, @@ -122,6 +123,7 @@ describe('SceneViewerContainerComponent', () => { normal, }); + expect(mockStore.dispatch).toHaveBeenCalledWith(initialAction); expect(mockStore.dispatch).toHaveBeenCalledWith(action); }, ); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index 2abe4572..b97f0f45 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -49,7 +49,7 @@ export class SceneViewerContainerComponent implements AfterViewInit { switch (selectedToolId) { case Tool.AddVoxel: this.store.dispatch( - addVoxel({ position: this.calcVoxelToAddPosition(pickInfo), value: 42 }), + addVoxel({ position: this.calcVoxelToAddPosition(pickInfo), value: 1 }), ); break; case Tool.RemoveVoxel: diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts index a9eab0b4..d68c5e6e 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts @@ -1,8 +1,9 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { SceneViewerService } from '@talus/ui'; +import { Coord } from '@talus/vdb'; import { of } from 'rxjs'; -import { catchError, map, tap } from 'rxjs/operators'; +import { catchError, map } from 'rxjs/operators'; import { GridService } from './grid.service'; import { addVoxel, @@ -28,7 +29,7 @@ export class SceneViewerContainerEffects { this.actions$.pipe( ofType(addVoxel), map(({ position, value }) => this.gridService.addVoxel(position, value)), - map(affectedOrigin => voxelAdded({ affectedOrigins: [affectedOrigin] })), + map(voxelAdded), catchError(() => of(addVoxelFailed())), ), ); @@ -37,7 +38,7 @@ export class SceneViewerContainerEffects { this.actions$.pipe( ofType(addVoxels), map(({ positions, values }) => this.gridService.addVoxels(positions, values)), - map(affectedOrigins => voxelsAdded({ affectedOrigins })), + map(voxelChanges => voxelsAdded({ voxelChanges })), catchError(() => of(addVoxelsFailed())), ), ); @@ -46,7 +47,7 @@ export class SceneViewerContainerEffects { this.actions$.pipe( ofType(removeVoxel), map(({ position }) => this.gridService.removeVoxel(position)), - map(affectedOrigin => voxelRemoved({ affectedOrigins: [affectedOrigin] })), + map(voxelRemoved), catchError(() => of(removeVoxelFailed())), ), ); @@ -54,16 +55,27 @@ export class SceneViewerContainerEffects { updateGridMesh$ = createEffect( () => this.actions$.pipe( - ofType(voxelAdded, voxelsAdded, voxelRemoved), - tap({ - next: ({ affectedOrigins }) => { - affectedOrigins.map(origin => { - const mesh = this.gridService.computeInternalNode1Mesh(origin); - this.sceneViewerService.updateNodeMesh(mesh, origin); - }); - }, - }), + ofType(voxelAdded, voxelRemoved), + map(({ affectedNodeOrigin }) => this.computeAndUpdateNodeMesh(affectedNodeOrigin)), ), { dispatch: false }, ); + + updateGridMeshMultiple$ = createEffect( + () => + this.actions$.pipe( + ofType(voxelsAdded), + map(({ voxelChanges }) => + voxelChanges.map(change => { + this.computeAndUpdateNodeMesh(change.affectedNodeOrigin); + }), + ), + ), + { dispatch: false }, + ); + + private computeAndUpdateNodeMesh(affectedNodeOrigin: Coord): void { + const mesh = this.gridService.computeInternalNode1Mesh(affectedNodeOrigin); + this.sceneViewerService.updateNodeMesh(mesh, affectedNodeOrigin); + } } diff --git a/apps/frontend/src/app/undo-redo/undo-redo.actions.ts b/apps/frontend/src/app/undo-redo/undo-redo.actions.ts index c1bf041d..a797592b 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.actions.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.actions.ts @@ -4,7 +4,12 @@ const actionTypePrefix = `[undoRedo]`; export const addUndo = createAction( `${actionTypePrefix} Add undo`, - props<{ redoAction: Action; undoAction: Action }>(), + props<{ + redoStartAction: Action; + redoEndActionType: string; + undoStartAction: Action; + undoEndActionType: string; + }>(), ); export const undo = createAction(`${actionTypePrefix} Undo`); diff --git a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts index 65d2a52c..82ce29c0 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts @@ -4,7 +4,12 @@ import { Action, select, Store } from '@ngrx/store'; import { filter, map, switchMap, withLatestFrom } from 'rxjs/operators'; import * as fromApp from '../app.reducer'; import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions'; -import { addVoxel, removeVoxel } from '../scene-viewer-container/scene-viewer-container.actions'; +import { + addVoxel, + removeVoxel, + voxelAdded, + voxelRemoved, +} from '../scene-viewer-container/scene-viewer-container.actions'; import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; @Injectable() @@ -14,9 +19,9 @@ export class UndoRedoEffects { undo$ = createEffect(() => this.actions$.pipe( ofType(undo, menuBarContainerActions.undo), - withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoAction))), + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoStartAction))), switchMap(([action, currentUndoAction]) => - currentUndoAction ? [currentUndoAction, undone()] : [undone()], + currentUndoAction ? [currentUndoAction] : [undone()], ), ), ); @@ -24,36 +29,83 @@ export class UndoRedoEffects { redo$ = createEffect(() => this.actions$.pipe( ofType(redo, menuBarContainerActions.redo), - withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoAction))), + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoStartAction))), switchMap(([action, currentRedoAction]) => - currentRedoAction ? [currentRedoAction, redone()] : [redone()], + currentRedoAction ? [currentRedoAction] : [redone()], ), ), ); + undoTriggeredActions$ = this.actions$.pipe( + withLatestFrom(this.store.pipe(select(fromApp.selectUndoRedoState))), + filter(([action, state]) => state.isUndoing), + map(([action, state]) => action), + ); + + undone$ = createEffect(() => + this.undoTriggeredActions$.pipe( + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoEndAction))), + filter(([action, undoEndAction]) => action.type === undoEndAction), + map(() => undone()), + ), + ); + + redoTriggeredActions$ = this.actions$.pipe( + withLatestFrom(this.store.pipe(select(fromApp.selectUndoRedoState))), + filter(([action, state]) => state.isRedoing), + map(([action, state]) => action), + ); + + redone$ = createEffect(() => + this.redoTriggeredActions$.pipe( + withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoEndAction))), + filter(([action, redoEndAction]) => action.type === redoEndAction), + map(() => redone()), + ), + ); + userTriggeredActions$ = this.actions$.pipe( withLatestFrom(this.store.pipe(select(fromApp.selectUndoRedoState))), - filter(([action, state]) => !state.isUndoRedoing), + filter(([action, state]) => !state.isUndoing && !state.isRedoing), map(([action, state]) => action), ); addUndoActionForAddVoxel$ = createEffect(() => this.userTriggeredActions$.pipe( - ofType(addVoxel), - map(action => [action, removeVoxel({ position: action.position })]), - map(this.createAddUndo), + ofType(voxelAdded), + map(voxelChange => ({ + redoStartAction: addVoxel(voxelChange), + redoEndAction: voxelAdded.type, + undoStartAction: removeVoxel({ position: voxelChange.position }), + undoEndActionType: voxelRemoved.type, + })), + map(({ redoStartAction, redoEndAction, undoStartAction, undoEndActionType }) => + this.createAddUndo(redoStartAction, redoEndAction, undoStartAction, undoEndActionType), + ), ), ); addUndoActionForRemoveVoxel$ = createEffect(() => this.userTriggeredActions$.pipe( - ofType(removeVoxel), - map(action => [action, addVoxel({ position: action.position, value: 42 })]), - map(this.createAddUndo), + ofType(voxelRemoved), + map(voxelChange => ({ + redoStartAction: removeVoxel({ position: voxelChange.position }), + redoEndAction: voxelRemoved.type, + undoStartAction: addVoxel(voxelChange), + undoEndActionType: voxelAdded.type, + })), + map(({ redoStartAction, redoEndAction, undoStartAction, undoEndActionType }) => + this.createAddUndo(redoStartAction, redoEndAction, undoStartAction, undoEndActionType), + ), ), ); - createAddUndo([redoAction, undoAction]: Action[]): Action { - return addUndo({ redoAction, undoAction }); + createAddUndo( + redoStartAction: Action, + redoEndActionType: string, + undoStartAction: Action, + undoEndActionType: string, + ): Action { + return addUndo({ redoStartAction, redoEndActionType, undoStartAction, undoEndActionType }); } } diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts index ad36de14..565251e3 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.ts @@ -12,16 +12,22 @@ export const featureKey = 'undoRedo'; export interface State { currentIndex: number; - isUndoRedoing: boolean; - redoActions: Action[]; - undoActions: Action[]; + isRedoing: boolean; + isUndoing: boolean; + redoEndActionTypes: string[]; + redoStartActions: Action[]; + undoEndActionTypes: string[]; + undoStartActions: Action[]; } export const initialState: State = { currentIndex: -1, - isUndoRedoing: false, - redoActions: [], - undoActions: [], + isRedoing: false, + isUndoing: false, + redoEndActionTypes: [], + redoStartActions: [], + undoEndActionTypes: [], + undoStartActions: [], }; const maxBufferSize = 10; @@ -30,24 +36,38 @@ const maxBufferIndex = maxBufferSize - 1; export const reducer = createReducer( initialState, - on(addUndo, (state, { redoAction, undoAction }) => { - const newIndex = state.currentIndex + 1; + on( + addUndo, + (state, { redoStartAction, redoEndActionType, undoStartAction, undoEndActionType }) => { + const newIndex = state.currentIndex + 1; + + const redoStartActions = state.redoStartActions.slice(0, newIndex); + const redoEndActionTypes = state.redoEndActionTypes.slice(0, newIndex); + const undoStartActions = state.undoStartActions.slice(0, newIndex); + const undoEndActionTypes = state.undoEndActionTypes.slice(0, newIndex); - const redoActions = state.redoActions.slice(0, newIndex); - const undoActions = state.undoActions.slice(0, newIndex); + return { + ...state, + currentIndex: newIndex > maxBufferIndex ? maxBufferIndex : newIndex, + redoStartActions: [...redoStartActions.slice(-maxBufferIndex), redoStartAction], + redoEndActionTypes: [...redoEndActionTypes.slice(-maxBufferIndex), redoEndActionType], + undoStartActions: [...undoStartActions.slice(-maxBufferIndex), undoStartAction], + undoEndActionTypes: [...undoEndActionTypes.slice(-maxBufferIndex), undoEndActionType], + }; + }, + ), + on(undo, menuBarContainerActions.undo, state => { return { ...state, - currentIndex: newIndex > maxBufferIndex ? maxBufferIndex : newIndex, - redoActions: [...redoActions.slice(-maxBufferIndex), redoAction], - undoActions: [...undoActions.slice(-maxBufferIndex), undoAction], + isUndoing: true, }; }), - on(undo, menuBarContainerActions.undo, redo, menuBarContainerActions.redo, state => { + on(redo, menuBarContainerActions.redo, state => { return { ...state, - isUndoRedoing: true, + isRedoing: true, }; }), @@ -56,22 +76,28 @@ export const reducer = createReducer( return { ...state, - isUndoRedoing: false, + isUndoing: false, currentIndex: newIndex < 0 ? -1 : newIndex, }; }), on(redone, state => { const newIndex = state.currentIndex + 1; - const maxRedoIndex = state.redoActions.length - 1; + const maxRedoIndex = state.redoStartActions.length - 1; return { ...state, - isUndoRedoing: false, + isRedoing: false, currentIndex: newIndex > maxRedoIndex ? maxRedoIndex : newIndex, }; }), ); -export const selectCurrentUndoAction = (state: State) => state.undoActions[state.currentIndex]; -export const selectCurrentRedoAction = (state: State) => state.redoActions[state.currentIndex + 1]; +export const selectCurrentRedoStartAction = (state: State) => + state.redoStartActions[state.currentIndex + 1]; +export const selectCurrentRedoEndAction = (state: State) => + state.redoEndActionTypes[state.currentIndex + 1]; +export const selectCurrentUndoStartAction = (state: State) => + state.undoStartActions[state.currentIndex]; +export const selectCurrentUndoEndAction = (state: State) => + state.undoEndActionTypes[state.currentIndex]; diff --git a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts index a221ae6c..4ac01600 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts @@ -9,7 +9,7 @@ describe('nodeToMesh()', () => { accessor.setValue([0, 0, 0], 1); accessor.setValue([0, 0, 1], 1); - const meshData = nodeToMesh(grid.tree.root); + const meshData = nodeToMesh(grid.tree.root, () => [0, 0, 0, 1]); const voxels = 2; diff --git a/libs/vdb/src/lib/tools/node-to-mesh.ts b/libs/vdb/src/lib/tools/node-to-mesh.ts index 321478fb..d666417f 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.ts @@ -30,19 +30,19 @@ export interface MeshData { * instead of 24 positions and 32 indices for a cube. * See: https://doc.babylonjs.com/how_to/optimizing_your_scene#using-unindexed-meshes */ -export function nodeToMesh(node: HashableNode): MeshData | undefined { +export function nodeToMesh( + node: HashableNode, + valueToColor: (value: T) => [number, number, number, number], +): MeshData | undefined { const mesh: MeshData = { colors: [], positions: [], normals: [], }; - const r = Math.random(); - const g = Math.random(); - const b = Math.random(); - for (const voxel of node.beginVoxelOn()) { const [x, y, z] = voxel.globalCoord; + const [r, g, b, a] = valueToColor(voxel.value); const v0 = [x, y, z]; const v1 = [x + 1, y, z]; @@ -301,147 +301,147 @@ export function nodeToMesh(node: HashableNode): MeshData | undefined { r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, r, g, b, - 1, + a, ); } From 1b569df30c977a1dcc64b9a8ddb5bc147f20daf5 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 15 Jan 2020 11:33:58 +0100 Subject: [PATCH 45/67] build(dep): update dependencies --- package.json | 16 +++---- yarn.lock | 126 +++++++++++++++++++++++++-------------------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index c7ed7855..f2688ed0 100644 --- a/package.json +++ b/package.json @@ -44,12 +44,12 @@ "@angular/platform-browser": "8.2.14", "@angular/platform-browser-dynamic": "8.2.14", "@angular/router": "8.2.14", - "@babylonjs/core": "4.1.0-beta.18", - "@babylonjs/materials": "4.1.0-beta.18", + "@babylonjs/core": "4.1.0-beta.20", + "@babylonjs/materials": "4.1.0-beta.20", "@ngrx/effects": "8.6.0", "@ngrx/store": "8.6.0", "@nrwl/angular": "8.11.0", - "core-js": "3.6.2", + "core-js": "3.6.4", "hammerjs": "2.0.8", "mnemonist": "0.32.0", "rxjs": "6.5.4", @@ -60,15 +60,15 @@ "@angular/cli": "8.3.22", "@angular/compiler-cli": "8.2.14", "@angular/language-service": "8.2.14", - "@babylonjs/inspector": "4.1.0-beta.18", + "@babylonjs/inspector": "4.1.0-beta.20", "@nrwl/cypress": "8.11.0", "@nrwl/jest": "8.11.0", "@nrwl/node": "8.11.0", "@nrwl/workspace": "8.11.0", "@types/benchmark": "1.0.31", - "@types/jest": "24.0.25", - "@types/node": "13.1.5", - "babylonjs": "4.1.0-beta.18", + "@types/jest": "24.9.0", + "@types/node": "13.1.7", + "babylonjs": "4.1.0-beta.20", "benchmark": "2.1.4", "codelyzer": "5.2.1", "cypress": "3.8.1", @@ -86,7 +86,7 @@ "stylelint-config-standard": "19.0.0", "stylelint-scss": "3.13.0", "ts-jest": "24.3.0", - "ts-node": "8.5.4", + "ts-node": "8.6.2", "tslint": "5.20.1", "typescript": "3.5.3" } diff --git a/yarn.lock b/yarn.lock index edf45950..fe381a2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1534,58 +1534,58 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babylonjs/core@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.18.tgz#8d4cde4e8c791f1ff979d3a95834fcb78980970b" - integrity sha512-P4k/9aMmiMPU8YG+zJy0PZRog0cOqSplApHa8KtqdexILdQECM09jpFmv4ql2SCKXF643TD4+Iqv56TXzqfuDw== +"@babylonjs/core@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/core/-/core-4.1.0-beta.20.tgz#fa554a10127e9409bec56b5c77256374b0524390" + integrity sha512-vKVaRNTGz/SgOljfhRhSJaAKajjkoXQQE5AgtdUz6zc4ps+9YPqV4sIFTS8jCSREnlnwpyLe7F8MjVYw4O51Aw== dependencies: tslib "^1.10.0" -"@babylonjs/gui@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.18.tgz#43142a5b32c49e1453aa61a7cbe359b3c8f4af56" - integrity sha512-onsQLXTp9jipvlBcy34U9U1Du6fM2IGcBzFt0aU27rpsKSNauLcveKP8oteHluNRqBWRHranoLDeipnEy0rGbQ== +"@babylonjs/gui@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/gui/-/gui-4.1.0-beta.20.tgz#20933a191eb8ec6b1c49c809eea5af0f9da62856" + integrity sha512-dxLiAvfrgqaE+LMaulcpb40VYe2VIgWjf/SrHKPNnV7SY9dvaxBjqH7+1J7E8zO0e3n8i6nFuUWZ9ij2lKcGsQ== dependencies: - "@babylonjs/core" "4.1.0-beta.18" + "@babylonjs/core" "4.1.0-beta.20" tslib "^1.10.0" -"@babylonjs/inspector@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.18.tgz#a42b0ce0baae40f5b0d67752dbe98b988199561e" - integrity sha512-1/bNWlqjZZ5uTwByuXhtRRwnA2WKXb6F1YFRJHIJ0ZtdW94y+UNzY43pBVQVD1A/7fY2G9P9tbdP0OF4M/JdLA== - dependencies: - "@babylonjs/core" "4.1.0-beta.18" - "@babylonjs/gui" "4.1.0-beta.18" - "@babylonjs/loaders" "4.1.0-beta.18" - "@babylonjs/materials" "4.1.0-beta.18" - "@babylonjs/serializers" "4.1.0-beta.18" - babylonjs-gltf2interface "4.1.0-beta.18" +"@babylonjs/inspector@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/inspector/-/inspector-4.1.0-beta.20.tgz#79224464a772bcf470c3ef352d117560a771356d" + integrity sha512-aonk4bArPhZ+HPj5J13BAyqD/QHBxcAr4oZZgim2DQXjuC40f6ClUYRQH/p0hPJYoy3uR0GiTOvWxx/MPhCOiQ== + dependencies: + "@babylonjs/core" "4.1.0-beta.20" + "@babylonjs/gui" "4.1.0-beta.20" + "@babylonjs/loaders" "4.1.0-beta.20" + "@babylonjs/materials" "4.1.0-beta.20" + "@babylonjs/serializers" "4.1.0-beta.20" + babylonjs-gltf2interface "4.1.0-beta.20" tslib "^1.10.0" -"@babylonjs/loaders@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.18.tgz#09cd54ad6440570e8b024b515b1f739c471c8f58" - integrity sha512-Dsh4pxVFoqIeg1A5hWN281QSPotWMroqSMS3Zrm7KejKvdcT9J4NqFneYyMSMZyBBIMCdoYAdsF2w1gfkWW9ww== +"@babylonjs/loaders@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/loaders/-/loaders-4.1.0-beta.20.tgz#31c910fb5f72a3049688181c7c0ffbdd519e8f4e" + integrity sha512-zNqCjb9vR4oArVaOPMqnKMQFzRe3gw0aSY56oBfMisfcwilWRD9Dcc9dy4gn7m5VgPUTIMtMrBfRnrDerNK1yA== dependencies: - "@babylonjs/core" "4.1.0-beta.18" - babylonjs-gltf2interface "4.1.0-beta.18" + "@babylonjs/core" "4.1.0-beta.20" + babylonjs-gltf2interface "4.1.0-beta.20" tslib "^1.10.0" -"@babylonjs/materials@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.18.tgz#7a3e01eff726041a59e13f84fb89099bd629cec9" - integrity sha512-iC3qvwLfMkKDO8ALRiw1xqTjaXoaDPGuKvN6SIZQYTgnBTGLt+Zl6wZ6Org76QwUdqyOwgnyJasg+m56SgmY9g== +"@babylonjs/materials@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/materials/-/materials-4.1.0-beta.20.tgz#67a3368a894ffa645999a068f995c0802497a7c1" + integrity sha512-uQSaFdQAKdZC/9CLEufvDyQ37SsPC2zuZt9awugB20tRCsYuj0q6FWmrGR+hleVsOoq/xm9e8y0vnf1Kx9F5bg== dependencies: - "@babylonjs/core" "4.1.0-beta.18" + "@babylonjs/core" "4.1.0-beta.20" tslib "^1.10.0" -"@babylonjs/serializers@4.1.0-beta.18": - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.18.tgz#1a36debb01d59b67fc7ff6cfec318eb215bc0548" - integrity sha512-U12cY43vIZf5ULvPt6A6pDp8meYdabHjSAsPExulRLy6cxhbZcWLJrXBif6ugKOz8y1Ow8GiPO0NtPVbfl8YBg== +"@babylonjs/serializers@4.1.0-beta.20": + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/@babylonjs/serializers/-/serializers-4.1.0-beta.20.tgz#9ce3f3661c9d4246c1215a97482df1d86c3a12ef" + integrity sha512-BWMXr0DxGC1hNOiDaQ2FKlueBP3bdFTs98uoo+sWarKhiaOwKkast8DF7QZnEyZVR6oPvUr06FEYmWZnVgidQg== dependencies: - "@babylonjs/core" "4.1.0-beta.18" - babylonjs-gltf2interface "4.1.0-beta.18" + "@babylonjs/core" "4.1.0-beta.20" + babylonjs-gltf2interface "4.1.0-beta.20" tslib "^1.10.0" "@cnakazawa/watch@^1.0.3": @@ -2026,10 +2026,10 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@24.0.25": - version "24.0.25" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f" - integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g== +"@types/jest@24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.0.tgz#78c6991cd1734cf0d390be24875e310bb0a9fb74" + integrity sha512-dXvuABY9nM1xgsXlOtLQXJKdacxZJd7AtvLsKZ/0b57ruMXDKCOXAC/M75GbllQX6o1pcZ5hAG4JzYy7Z/wM2w== dependencies: jest-diff "^24.3.0" @@ -2048,10 +2048,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== -"@types/node@13.1.5": - version "13.1.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.5.tgz#4d5efc52a1d3e45d13e5ec9f911cbc5b089ccaec" - integrity sha512-wupvfmtbqRJzjCm1H2diy7wo31Gn1OzvqoxCfQuKM9eSecogzP0WTlrjdq7cf7jgSO2ZX6hxwgRPR8Wt7FA22g== +"@types/node@13.1.7": + version "13.1.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.7.tgz#db51d28b8dfacfe4fb2d0da88f5eb0a2eca00675" + integrity sha512-HU0q9GXazqiKwviVxg9SI/+t/nAsGkvLDkIdxz+ObejG2nX6Si00TeLqHMoS+a/1tjH7a8YpKVQwtgHuMQsldg== "@types/parse-json@^4.0.0": version "4.0.0" @@ -2846,15 +2846,15 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -babylonjs-gltf2interface@4.1.0-beta.18: - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.18.tgz#afc333500bc60066d364769f17b1bddb540754b0" - integrity sha512-DIsZ0/NhmQ9XI7mPcvqfwCdhZn6l6yiJWvHMmsTFLHaIaVUhDiUomjxAF4yPIYeX2PbtmxkJpv4TJY7QnXF9MA== +babylonjs-gltf2interface@4.1.0-beta.20: + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/babylonjs-gltf2interface/-/babylonjs-gltf2interface-4.1.0-beta.20.tgz#90368bda475b3857b3043913d6358f8c4604d05b" + integrity sha512-Y3hGTh+5Yhywc7k8p8n49KKk3Od8u9pSgIp4OOjxliGSuRtc301chifpfVThgcs7UVoowfCXXxdB6mrUzRnFXw== -babylonjs@4.1.0-beta.18: - version "4.1.0-beta.18" - resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.18.tgz#e0c2bfe10d960adba1c5425c3c4b77c5b5fc48da" - integrity sha512-9hblkZ5Y0n16e4SBDMIglsMRpvMuLgE2IvqoTOhWHWLMJX6jtX75ZnLhBFjGIjlvO3L18H1vCUQRgIcS29wotg== +babylonjs@4.1.0-beta.20: + version "4.1.0-beta.20" + resolved "https://registry.yarnpkg.com/babylonjs/-/babylonjs-4.1.0-beta.20.tgz#46ce13e315f37e98d8930c561f49f81761b6c704" + integrity sha512-FU52D50wsS3Gr/VXWmLEKAqCOA4tuw+BIPJWnCaKmTN644k9IKyzOsZnMz+WulyC29Uce3duUKgv+PCpRMCKig== bail@^1.0.0: version "1.0.4" @@ -3824,10 +3824,10 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.2.tgz#2799ea1a59050f0acf50dfe89b916d6503b16caa" - integrity sha512-hIE5dXkRzRvnZ5vhkRfQxUvDxQZmD9oueA08jDYRBKJHx+VIl/Pne/e0A4x9LObEEthC/TqiZybUoNM4tRgnKg== +core-js@3.6.4: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" + integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw== core-js@^2.4.0: version "2.6.9" @@ -10668,16 +10668,16 @@ ts-loader@5.4.5: micromatch "^3.1.4" semver "^5.0.1" -ts-node@8.5.4: - version "8.5.4" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" - integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== +ts-node@8.6.2: + version "8.6.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.6.2.tgz#7419a01391a818fbafa6f826a33c1a13e9464e35" + integrity sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg== dependencies: arg "^4.1.0" diff "^4.0.1" make-error "^1.1.1" source-map-support "^0.5.6" - yn "^3.0.0" + yn "3.1.1" tsconfig-paths-webpack-plugin@3.2.0: version "3.2.0" @@ -11618,7 +11618,7 @@ yauzl@2.4.1: dependencies: fd-slicer "~1.0.1" -yn@^3.0.0: +yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From ce544f56cb59c14c4d0348ef904b3c5d9f3bafe5 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 15 Jan 2020 11:36:24 +0100 Subject: [PATCH 46/67] build(dep): update cypress to `v3.8.2` --- .circleci/config.yml | 2 +- package.json | 2 +- yarn.lock | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 24488b48..d271bbd8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,7 +17,7 @@ aliases: - &use_docker_cypress_included docker: # 3.8.0 fails with `Error: write EPIPE` when running `benchmark`!? - - image: cypress/included:3.8.1 + - image: cypress/included:3.8.2 - &workspace ~/talus diff --git a/package.json b/package.json index f2688ed0..23eca823 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "babylonjs": "4.1.0-beta.20", "benchmark": "2.1.4", "codelyzer": "5.2.1", - "cypress": "3.8.1", + "cypress": "3.8.2", "dotenv": "8.2.0", "gh-pages": "2.2.0", "jasmine-marbles": "0.6.0", diff --git a/yarn.lock b/yarn.lock index fe381a2f..af84ef50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3993,10 +3993,10 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.1.tgz#7821084e0ead81d35ffa29f2141c977dfdfc2343" - integrity sha512-eLk5OpL/ZMDfQx9t7ZaDUAGVcvSOPTi7CG1tiUnu9BGk7caBiDhuFi3Tz/D5vWqH/Dl6Uh4X+Au4W+zh0xzbXw== +cypress@3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.2.tgz#58fa96e1e7dae712403b0f4e8af1efe35442ff7a" + integrity sha512-aTs0u3+dfEuLe0Ct0FVO5jD1ULqxbuqWUZwzBm0rxdLgLxIAOI/A9f/WkgY5Cfy1TEXe8pKC6Wal0ZpnkdGRSw== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" @@ -4009,6 +4009,7 @@ cypress@3.8.1: commander "2.15.1" common-tags "1.8.0" debug "3.2.6" + eventemitter2 "4.1.2" execa "0.10.0" executable "4.1.1" extract-zip "1.6.7" @@ -4577,6 +4578,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= +eventemitter2@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-4.1.2.tgz#0e1a8477af821a6ef3995b311bf74c23a5247f15" + integrity sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU= + eventemitter3@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" From 917f489a14feff580f4a6505cb8d4378b438c456 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Wed, 15 Jan 2020 11:38:28 +0100 Subject: [PATCH 47/67] build(dep): update stylelint to `v13.0.0` --- package.json | 2 +- yarn.lock | 404 ++++++++++++++++++++++++++++----------------------- 2 files changed, 223 insertions(+), 183 deletions(-) diff --git a/package.json b/package.json index 23eca823..4b63e8b6 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "jest-preset-angular": "7.1.1", "junit-xml": "1.2.0", "prettier": "1.19.1", - "stylelint": "12.0.1", + "stylelint": "13.0.0", "stylelint-config-recommended": "3.0.0", "stylelint-config-recommended-scss": "4.1.0", "stylelint-config-standard": "19.0.0", diff --git a/yarn.lock b/yarn.lock index af84ef50..adfc6408 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1774,14 +1774,6 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - "@ngrx/effects@8.6.0": version "8.6.0" resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-8.6.0.tgz#a0d7339597a5128c5cf896ddcf93f73406a45860" @@ -1803,10 +1795,26 @@ tree-kill "1.2.1" webpack-sources "1.4.3" -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" "@nrwl/angular@8.11.0": version "8.11.0" @@ -2043,6 +2051,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + "@types/node@*": version "12.7.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" @@ -2053,6 +2066,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.7.tgz#db51d28b8dfacfe4fb2d0da88f5eb0a2eca00675" integrity sha512-HU0q9GXazqiKwviVxg9SI/+t/nAsGkvLDkIdxz+ObejG2nX6Si00TeLqHMoS+a/1tjH7a8YpKVQwtgHuMQsldg== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -2549,11 +2567,6 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2564,13 +2577,18 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-union@^1.0.1, array-union@^1.0.2: +array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -2682,17 +2700,17 @@ autoprefixer@9.6.1: postcss "^7.0.17" postcss-value-parser "^4.0.0" -autoprefixer@^9.7.1: - version "9.7.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.2.tgz#26cf729fbb709323b40171a874304884dcceffed" - integrity sha512-LCAfcdej1182uVvPOZnytbq61AhnOZ/4JelDaJGDeNwewyU1AMaNthcHsyz1NRjTmd2FkurMckLWfkHg3Z//KA== +autoprefixer@^9.7.3: + version "9.7.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" + integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== dependencies: - browserslist "^4.7.3" - caniuse-lite "^1.0.30001010" + browserslist "^4.8.3" + caniuse-lite "^1.0.30001020" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.23" + postcss "^7.0.26" postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: @@ -3069,7 +3087,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.8.3: +browserslist@4.8.3, browserslist@^4.8.3: version "4.8.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44" integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg== @@ -3087,15 +3105,6 @@ browserslist@^4.6.0, browserslist@^4.6.3, browserslist@^4.6.6: electron-to-chromium "^1.3.191" node-releases "^1.1.25" -browserslist@^4.7.3: - version "4.7.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.3.tgz#02341f162b6bcc1e1028e30624815d4924442dc3" - integrity sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ== - dependencies: - caniuse-lite "^1.0.30001010" - electron-to-chromium "^1.3.306" - node-releases "^1.1.40" - browserslist@^4.8.2: version "4.8.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289" @@ -3237,11 +3246,6 @@ cachedir@1.3.0: dependencies: os-homedir "^1.0.1" -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -3266,14 +3270,14 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= +camelcase-keys@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.1.1.tgz#0d24dde78cea4c7d2da7f4ea40b7995083328c8d" + integrity sha512-kEPCddRFChEzO0d6w61yh0WbBiSv9gBnfZWGfXRYPlGqIdIGef6HMR6pgqVSEWCYkrp8B0AtEpEXNY+Jx0xk1A== dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" camelcase@^4.1.0: version "4.1.0" @@ -3295,11 +3299,6 @@ caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== -caniuse-lite@^1.0.30001010: - version "1.0.30001012" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001012.tgz#653ec635e815b9e0fb801890923b0c2079eb34ec" - integrity sha512-7RR4Uh04t9K1uYRWzOJmzplgEOAXbfK72oVNokCdMzA67trrhPzy93ahKk1AWHiA0c58tD2P+NHqxrA8FZ+Trg== - caniuse-lite@^1.0.30001015: version "1.0.30001016" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz#16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66" @@ -3310,6 +3309,11 @@ caniuse-lite@^1.0.30001017: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001020.tgz#3f04c1737500ffda78be9beb0b5c1e2070e15926" integrity sha512-yWIvwA68wRHKanAVS1GjN8vajAv7MBFshullKCeq/eKpK7pJBVDgFFEqvgWTkcP2+wIDeQGYFRXECjKZnLkUjA== +caniuse-lite@^1.0.30001020: + version "1.0.30001021" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001021.tgz#e75ed1ef6dbadd580ac7e7720bb16f07b083f254" + integrity sha512-wuMhT7/hwkgd8gldgp2jcrUjOU9RXJ4XxGumQeOsUr91l3WwmM68Cpa/ymCnWEDqakwFXhuDQbaKNHXBPgeE9g== + canonical-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" @@ -3981,13 +3985,6 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: dependencies: cssom "0.3.x" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -4096,7 +4093,7 @@ debuglog@^1.0.1: resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= -decamelize-keys@^1.0.0: +decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= @@ -4266,13 +4263,20 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.0.0, dir-glob@^2.2.2: +dir-glob@^2.0.0: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== dependencies: path-type "^3.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -4378,11 +4382,6 @@ electron-to-chromium@^1.3.191: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.230.tgz#2d0618cb6f724391d5fd0926dde84d6c67cbcda9" integrity sha512-r0RljY5DZi9RX4v8mjHxJkDWnQe+nsrkGlHtrDF2uvZcvAkw+iglvlQi1794gZhwRtJoDOomMJlDHL2LfXSCZA== -electron-to-chromium@^1.3.306: - version "1.3.314" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.314.tgz#c186a499ed2c9057bce9eb8dca294d6d5450facc" - integrity sha512-IKDR/xCxKFhPts7h+VaSXS02Z1mznP3fli1BbXWXeN89i2gCzKraU8qLpEid8YzKcmZdZD3Mly3cn5/lY9xsBQ== - electron-to-chromium@^1.3.322: version "1.3.322" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" @@ -4810,17 +4809,16 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-glob@^2.2.6: - version "2.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== +fast-glob@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" fast-json-stable-stringify@2.0.0, fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -4837,6 +4835,13 @@ fastparse@^1.1.1: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -4977,7 +4982,7 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -4991,7 +4996,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -5250,18 +5255,13 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -glob-parent@~5.1.0: +glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== dependencies: is-glob "^4.0.1" -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - glob@7.0.x: version "7.0.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" @@ -5319,6 +5319,18 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globby@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" + integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -5342,20 +5354,6 @@ globby@^7.1.1: pify "^3.0.0" slash "^1.0.0" -globby@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" - integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^1.0.2" - dir-glob "^2.2.2" - fast-glob "^2.2.6" - glob "^7.1.3" - ignore "^4.0.3" - pify "^4.0.1" - slash "^2.0.0" - globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" @@ -5417,6 +5415,11 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +hard-rejection@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -5704,11 +5707,6 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^4.0.3: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" @@ -5779,6 +5777,11 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -7180,14 +7183,6 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -7276,10 +7271,10 @@ map-obj@^1.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= +map-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" + integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== map-visit@^1.0.0: version "1.0.0" @@ -7353,20 +7348,22 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" +meow@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-6.0.0.tgz#949196fdf21d979379e3bdccb0411e60f8cffd93" + integrity sha512-x4rYsjigPBDAxY+BGuK83YLhUIqui5wYyZoqb6QJCUOs+0fiYq+i/NV4Jt8OgIfObZFxG9iTyvLDu4UTohGTFw== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.1.1" + decamelize-keys "^1.1.0" + hard-rejection "^2.0.0" + minimist-options "^4.0.1" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.0" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.8.1" + yargs-parser "^16.1.0" merge-descriptors@1.0.1: version "1.0.1" @@ -7378,10 +7375,10 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3" - integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A== +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== methods@~1.1.2: version "1.1.2" @@ -7460,6 +7457,11 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" + integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= + mini-css-extract-plugin@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#81d41ec4fe58c713a96ad7c723cdb2d0bd4d70e1" @@ -7487,10 +7489,10 @@ minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== +minimist-options@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.0.2.tgz#29c4021373ded40d546186725e57761e4b1984a7" + integrity sha512-seq4hpWkYSUh1y7NXxzucwAN9yVlBc3Upgdjz8vLCP97jG8kaOmzYrVH/m7tQ1NYD1wdtZbSLfdy4zFmRWuc/w== dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" @@ -7756,13 +7758,6 @@ node-releases@^1.1.25: dependencies: semver "^5.3.0" -node-releases@^1.1.40: - version "1.1.41" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.41.tgz#57674a82a37f812d18e3b26118aefaf53a00afed" - integrity sha512-+IctMa7wIs8Cfsa8iYzeaLTFwv5Y4r5jZud+4AnfymzeEXKBCavFX0KBgzVaPVqf0ywa6PrO8/b+bPqdwjGBSg== - dependencies: - semver "^6.3.0" - node-releases@^1.1.42: version "1.1.43" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2" @@ -7785,7 +7780,7 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -8640,7 +8635,7 @@ postcss@7.0.17, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17 source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.21, postcss@^7.0.23: +postcss@^7.0.21: version "7.0.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1" integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ== @@ -8649,6 +8644,15 @@ postcss@^7.0.21, postcss@^7.0.23: source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.26: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -8832,10 +8836,10 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== -quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== ramda@0.24.1: version "0.24.1" @@ -8923,14 +8927,6 @@ read-package-tree@5.3.1: readdir-scoped-modules "^1.0.0" util-promisify "^2.1.0" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -8939,6 +8935,15 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" +read-pkg-up@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -8948,6 +8953,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -9010,13 +9025,13 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" + indent-string "^4.0.0" + strip-indent "^3.0.0" reflect-metadata@^0.1.2: version "0.1.13" @@ -9343,6 +9358,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -9384,6 +9404,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -10174,10 +10199,12 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" @@ -10241,12 +10268,12 @@ stylelint-scss@3.13.0: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.2" -stylelint@12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-12.0.1.tgz#5b1f3bf7333320acce322b49852c8b85e94ce7e4" - integrity sha512-1mn39pqZiC/e8KUPoRMc1WMM83Upb2ILaSGxkCvKxALHutEOs2txcPQocJiXdO4Zx4FY4prGqjlkwrbthAxqig== +stylelint@13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.0.0.tgz#532007f7154c1a5ed14245d857a5884316f5111f" + integrity sha512-6sjgOJbM3iLhnUtmRO0J1vvxie9VnhIZX/2fCehjylv9Gl9u0ytehGCTm9Lhw2p1F8yaNZn5UprvhCB8C3g/Tg== dependencies: - autoprefixer "^9.7.1" + autoprefixer "^9.7.3" balanced-match "^1.0.0" chalk "^3.0.0" cosmiconfig "^6.0.0" @@ -10255,7 +10282,7 @@ stylelint@12.0.1: file-entry-cache "^5.0.1" get-stdin "^7.0.0" global-modules "^2.0.0" - globby "^9.2.0" + globby "^11.0.0" globjoin "^0.1.4" html-tags "^3.1.0" ignore "^5.1.4" @@ -10266,10 +10293,10 @@ stylelint@12.0.1: lodash "^4.17.15" log-symbols "^3.0.0" mathml-tag-names "^2.1.1" - meow "^5.0.0" + meow "^6.0.0" micromatch "^4.0.2" normalize-selector "^0.2.0" - postcss "^7.0.21" + postcss "^7.0.26" postcss-html "^0.36.0" postcss-jsx "^0.36.3" postcss-less "^3.1.4" @@ -10589,10 +10616,10 @@ tree-kill@1.2.1: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== -trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= +trim-newlines@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" + integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== trim-repeated@^1.0.0: version "1.0.0" @@ -10765,7 +10792,12 @@ type-fest@^0.5.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== -type-fest@^0.8.0: +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -11510,7 +11542,7 @@ yargs-parser@10.0.0: dependencies: camelcase "^4.1.0" -yargs-parser@10.x, yargs-parser@^10.0.0: +yargs-parser@10.x: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== @@ -11533,6 +11565,14 @@ yargs-parser@^13.0.0, yargs-parser@^13.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" + integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" From 88cc433b58305f8a2b1ccf84ae8769abe9ead561 Mon Sep 17 00:00:00 2001 From: Philippe Morier Date: Thu, 16 Jan 2020 09:05:46 +0100 Subject: [PATCH 48/67] refactor(ui): prefix UI components with `Ui` like Angular does with `Mat` (#14) * refactor(ui): prefix `MenuBar` with `Ui` like Angular does with `Mat` * refactor(ui): prefix `SceneViewer` with `Ui` as Angular does with `Mat` * test(ui): check `menu-bar` menus & items * refactor(ui): remove ctor & onInit * test(ui): check if sidnav has left & right navigation * refactor(ui): prefix `SidenavShell` with `Ui` as Angular does with `Mat` * refactor(ui): prefix `SceneViewerService` with `Ui` (ng with `Mat`) * refactor(ui): prefix `SceneViewerTestModule` with `Ui` (ng with `Mat`) * refactor(ui): prefix `ToolbarModule` with `Ui` (ng with `Mat`) --- apps/frontend/src/app/app.component.spec.ts | 6 +- apps/frontend/src/app/app.module.ts | 4 +- .../menu-bar-container.module.ts | 4 +- .../scene-viewer-container.component.ts | 6 +- .../scene-viewer-container.effects.ts | 4 +- .../scene-viewer-container.module.ts | 4 +- .../src/app/tools-panel/tools-panel.module.ts | 4 +- libs/ui/jest.config.js | 4 +- .../lib/menu-bar/menu-bar.component.spec.ts | 81 +++++++++++++++++-- .../ui/src/lib/menu-bar/menu-bar.component.ts | 2 +- libs/ui/src/lib/menu-bar/menu-bar.module.ts | 8 +- libs/ui/src/lib/scene-viewer/index.ts | 2 +- .../scene-viewer.component.spec.ts | 16 ++-- .../scene-viewer/scene-viewer.component.ts | 6 +- .../scene-viewer.module.testing.ts | 12 +-- .../lib/scene-viewer/scene-viewer.module.ts | 12 +-- .../lib/scene-viewer/scene-viewer.service.ts | 2 +- .../sidenav-shell.component.spec.ts | 24 ++++-- .../sidenav-shell/sidenav-shell.component.ts | 14 ++-- .../lib/sidenav-shell/sidenav-shell.module.ts | 26 +++--- .../src/lib/toolbar/toolbar.component.spec.ts | 12 +-- libs/ui/src/lib/toolbar/toolbar.component.ts | 2 +- libs/ui/src/lib/toolbar/toolbar.module.ts | 8 +- libs/ui/tsconfig.spec.json | 2 +- package.json | 1 - yarn.lock | 26 ++++-- 26 files changed, 188 insertions(+), 104 deletions(-) diff --git a/apps/frontend/src/app/app.component.spec.ts b/apps/frontend/src/app/app.component.spec.ts index 20f333bc..49deb6a1 100644 --- a/apps/frontend/src/app/app.component.spec.ts +++ b/apps/frontend/src/app/app.component.spec.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { async, TestBed } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; -import { SceneViewerTestModule, SidenavShellModule } from '@talus/ui'; +import { UiSceneViewerTestModule, UiSidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; @Component({ @@ -38,8 +38,8 @@ describe('AppComponent', () => { imports: [ BrowserAnimationsModule, RouterTestingModule, - SidenavShellModule, - SceneViewerTestModule, + UiSceneViewerTestModule, + UiSidenavShellModule, ], }).compileComponents(); })); diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts index 67ca1a26..72df9030 100644 --- a/apps/frontend/src/app/app.module.ts +++ b/apps/frontend/src/app/app.module.ts @@ -4,7 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterModule } from '@angular/router'; import { EffectsModule } from '@ngrx/effects'; import { StoreModule } from '@ngrx/store'; -import { SidenavShellModule } from '@talus/ui'; +import { UiSidenavShellModule } from '@talus/ui'; import { AppComponent } from './app.component'; import { AppEffects } from './app.effects'; import { metaReducers, ROOT_REDUCERS } from './app.reducer'; @@ -39,7 +39,7 @@ import { UndoRedoModule } from './undo-redo/undo-redo.module'; MenuBarContainerModule, SceneViewerContainerModule, - SidenavShellModule, + UiSidenavShellModule, ToolsPanelModule, UndoRedoModule, ], diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts index b8d0c534..2347c696 100644 --- a/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.module.ts @@ -1,10 +1,10 @@ import { NgModule } from '@angular/core'; -import { MenuBarModule } from '@talus/ui'; +import { UiMenuBarModule } from '@talus/ui'; import { MenuBarContainerComponent } from './menu-bar-container.component'; @NgModule({ declarations: [MenuBarContainerComponent], - imports: [MenuBarModule], + imports: [UiMenuBarModule], exports: [MenuBarContainerComponent], }) export class MenuBarContainerModule {} diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index b97f0f45..9026d0b7 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -2,7 +2,7 @@ import { AfterViewInit, ChangeDetectionStrategy, Component, ViewChild } from '@a // import '@babylonjs/core/Rendering/edgesRenderer'; // import '@babylonjs/core/Rendering/outlineRenderer'; import { select, Store } from '@ngrx/store'; -import { PointerButton, PointerPickInfo, SceneViewerComponent } from '@talus/ui'; +import { PointerButton, PointerPickInfo, UiSceneViewerComponent } from '@talus/ui'; import { Coord } from '@talus/vdb'; import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; @@ -20,8 +20,8 @@ import { addVoxel, removeVoxel } from './scene-viewer-container.actions'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SceneViewerContainerComponent implements AfterViewInit { - @ViewChild(SceneViewerComponent, { static: false }) - private sceneViewerComponent: SceneViewerComponent; + @ViewChild(UiSceneViewerComponent, { static: false }) + private sceneViewerComponent: UiSceneViewerComponent; selectedToolId$: Observable = this.store.pipe(select(fromApp.selectSelectedToolId)); voxelCount$: Observable = this.store.pipe(select(fromApp.selectVoxelCount)); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts index d68c5e6e..03c7fe79 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.effects.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { SceneViewerService } from '@talus/ui'; +import { UiSceneViewerService } from '@talus/ui'; import { Coord } from '@talus/vdb'; import { of } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; @@ -22,7 +22,7 @@ export class SceneViewerContainerEffects { constructor( private actions$: Actions, private gridService: GridService, - private sceneViewerService: SceneViewerService, + private sceneViewerService: UiSceneViewerService, ) {} addVoxel$ = createEffect(() => diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts index ac65b3af..2c2622fe 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.module.ts @@ -1,7 +1,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { EffectsModule } from '@ngrx/effects'; -import { SceneViewerModule } from '@talus/ui'; +import { UiSceneViewerModule } from '@talus/ui'; import { GridService } from './grid.service'; import { SceneViewerContainerComponent } from './scene-viewer-container.component'; import { SceneViewerContainerEffects } from './scene-viewer-container.effects'; @@ -11,7 +11,7 @@ import { SceneViewerContainerEffects } from './scene-viewer-container.effects'; imports: [ CommonModule, EffectsModule.forFeature([SceneViewerContainerEffects]), - SceneViewerModule, + UiSceneViewerModule, ], exports: [SceneViewerContainerComponent], providers: [GridService], diff --git a/apps/frontend/src/app/tools-panel/tools-panel.module.ts b/apps/frontend/src/app/tools-panel/tools-panel.module.ts index 55db8f76..fc96800f 100644 --- a/apps/frontend/src/app/tools-panel/tools-panel.module.ts +++ b/apps/frontend/src/app/tools-panel/tools-panel.module.ts @@ -1,11 +1,11 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { ToolbarModule } from '@talus/ui'; +import { UiToolbarModule } from '@talus/ui'; import { ToolsPanelComponent } from './tools-panel.component'; @NgModule({ declarations: [ToolsPanelComponent], - imports: [CommonModule, ToolbarModule], + imports: [CommonModule, UiToolbarModule], exports: [ToolsPanelComponent], }) export class ToolsPanelModule {} diff --git a/libs/ui/jest.config.js b/libs/ui/jest.config.js index 35d35ffa..b2ed4000 100644 --- a/libs/ui/jest.config.js +++ b/libs/ui/jest.config.js @@ -21,11 +21,11 @@ module.exports = { ], // https://github.com/nrwl/nx/issues/1439#issuecomment-561268656 // When using `Run test` directly in WebStorm, change the used config to - // this file i.e. `./ui/jest.config.js` and not `/jest.config.js`. + // this file i.e. `./ui/jest.config.js` and not `/jest.config.js`. // Otherwise, following error might occur: // - Cannot find module '@talus/ui' // - Zone is needed for the async() test helper but could not be found. - setupFilesAfterEnv: ['./src/test-setup.ts'], + setupFilesAfterEnv: ['/src/test-setup.ts'], // https://github.com/thymikee/jest-preset-angular/issues/293#issuecomment-513544717 // When using `Run test` directly in WebStorm, the scss couldn't be loaded. diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts index 1d7c4150..86f2eba4 100644 --- a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts @@ -1,24 +1,89 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { MenuBarComponent } from './menu-bar.component'; -import { MenuBarModule } from './menu-bar.module'; +import { By } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { UiMenuBarModule } from '@talus/ui'; +import { UiMenuBarComponent } from './menu-bar.component'; -describe('MenuBarComponent', () => { - let component: MenuBarComponent; - let fixture: ComponentFixture; +describe('UiMenuBarComponent', () => { + let component: UiMenuBarComponent; + let fixture: ComponentFixture; + + const expectedMenus = [ + { + label: 'Menu 1', + menuItems: [ + { + label: 'Item 1.1', + icon: 'undo', + value: 'Value 1.1', + }, + ], + }, + { + label: 'Menu 2', + menuItems: [ + { + label: 'Item 2.1', + icon: 'undo', + value: 'Value 2.1', + }, + { + label: 'Item 2.2', + icon: 'undo', + value: 'Value 2.2', + }, + ], + }, + ]; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [MenuBarModule], + imports: [UiMenuBarModule, BrowserAnimationsModule], }).compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(MenuBarComponent); + fixture = TestBed.createComponent(UiMenuBarComponent); component = fixture.componentInstance; - fixture.detectChanges(); + // Don't call `detectChanges()`, because of `OnPush` + // See: https://github.com/angular/angular/issues/12313#issuecomment-301848232 + // fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should add all menus', () => { + component.menuConfig = { + menus: expectedMenus, + }; + fixture.detectChanges(); + + const menus = fixture.debugElement.queryAll(By.css('mat-menu')); + const menuButtons = fixture.debugElement.queryAll(By.css('button')); + + expect(menus.length).toEqual(expectedMenus.length); + expect(menuButtons.length).toEqual(expectedMenus.length); + expect(menuButtons[0].nativeElement.textContent).toContain(expectedMenus[0].label); + expect(menuButtons[1].nativeElement.textContent).toContain(expectedMenus[1].label); + }); + + it('should add all menu-items for second menu', () => { + component.menuConfig = { + menus: expectedMenus, + }; + fixture.detectChanges(); + + const menuButtons = fixture.debugElement.queryAll(By.css('button')); + menuButtons[1].nativeElement.click(); + fixture.detectChanges(); + + const menuItemButtons = fixture.debugElement.queryAll(By.css('button.mat-menu-item > span')); + expect(menuItemButtons.length).toEqual(expectedMenus[1].menuItems.length); + + menuItemButtons.forEach((menuItemButton, j) => { + expect(menuItemButton.nativeElement.textContent).toEqual(expectedMenus[1].menuItems[j].label); + }); + }); }); diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.ts index 35a0b300..010b1e28 100644 --- a/libs/ui/src/lib/menu-bar/menu-bar.component.ts +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.ts @@ -37,7 +37,7 @@ interface UiMenuBarMenuItem { styleUrls: ['./menu-bar.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MenuBarComponent { +export class UiMenuBarComponent { @Input() menuConfig: UiMenuBarConfig = { menus: [] }; @Output() menuItemClick = new EventEmitter(); diff --git a/libs/ui/src/lib/menu-bar/menu-bar.module.ts b/libs/ui/src/lib/menu-bar/menu-bar.module.ts index 63616842..cff9cb92 100644 --- a/libs/ui/src/lib/menu-bar/menu-bar.module.ts +++ b/libs/ui/src/lib/menu-bar/menu-bar.module.ts @@ -1,11 +1,11 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule } from '@angular/material'; -import { MenuBarComponent } from './menu-bar.component'; +import { UiMenuBarComponent } from './menu-bar.component'; @NgModule({ - declarations: [MenuBarComponent], + declarations: [UiMenuBarComponent], imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule], - exports: [MenuBarComponent], + exports: [UiMenuBarComponent], }) -export class MenuBarModule {} +export class UiMenuBarModule {} diff --git a/libs/ui/src/lib/scene-viewer/index.ts b/libs/ui/src/lib/scene-viewer/index.ts index 14b12407..9e369a7f 100644 --- a/libs/ui/src/lib/scene-viewer/index.ts +++ b/libs/ui/src/lib/scene-viewer/index.ts @@ -2,4 +2,4 @@ export * from './scene-viewer.component'; export * from './scene-viewer.module'; export * from './scene-viewer.module.testing'; export { PointerButton } from './pointer-button'; -export { PointerPickInfo, SceneViewerService } from './scene-viewer.service'; +export { PointerPickInfo, UiSceneViewerService } from './scene-viewer.service'; diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.spec.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.spec.ts index b9ae1951..abc1db3f 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.spec.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { SceneViewerComponent } from './scene-viewer.component'; -import { SceneViewerTestModule } from './scene-viewer.module.testing'; +import { UiSceneViewerComponent } from './scene-viewer.component'; +import { UiSceneViewerTestModule } from './scene-viewer.module.testing'; -describe('SceneViewerComponent', () => { - let component: SceneViewerComponent; - let fixture: ComponentFixture; +describe('UiSceneViewerComponent', () => { + let component: UiSceneViewerComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [SceneViewerComponent], - imports: [SceneViewerTestModule], + declarations: [UiSceneViewerComponent], + imports: [UiSceneViewerTestModule], }).compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(SceneViewerComponent); + fixture = TestBed.createComponent(UiSceneViewerComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts index 7363c467..58e40fcd 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.component.ts @@ -8,7 +8,7 @@ import { Output, ViewChild, } from '@angular/core'; -import { SceneViewerService } from './scene-viewer.service'; +import { UiSceneViewerService } from './scene-viewer.service'; @Component({ selector: 'ui-scene-viewer', @@ -18,8 +18,8 @@ import { SceneViewerService } from './scene-viewer.service'; styleUrls: ['./scene-viewer.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SceneViewerComponent implements OnInit { - constructor(private sceneViewerService: SceneViewerService) {} +export class UiSceneViewerComponent implements OnInit { + constructor(private sceneViewerService: UiSceneViewerService) {} @ViewChild('canvas', { static: true }) canvas: ElementRef; diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.module.testing.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.module.testing.ts index e5b28056..10527d82 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.module.testing.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.module.testing.ts @@ -4,7 +4,7 @@ import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera'; import { NullEngine } from '@babylonjs/core/Engines/nullEngine'; import { Vector3 } from '@babylonjs/core/Maths/math.vector'; import { Scene } from '@babylonjs/core/scene'; -import { CameraFactory, EngineFactory, SceneViewerService } from './scene-viewer.service'; +import { CameraFactory, EngineFactory, UiSceneViewerService } from './scene-viewer.service'; function testCameraFactory(): any { return { @@ -47,16 +47,16 @@ function testEngineFactor(): any { template: ``, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SceneViewerStubComponent {} +export class UiSceneViewerStubComponent {} @NgModule({ - declarations: [SceneViewerStubComponent], - exports: [SceneViewerStubComponent], + declarations: [UiSceneViewerStubComponent], + exports: [UiSceneViewerStubComponent], imports: [CommonModule], providers: [ { provide: CameraFactory, useValue: testCameraFactory() }, { provide: EngineFactory, useValue: testEngineFactor() }, - SceneViewerService, + UiSceneViewerService, ], }) -export class SceneViewerTestModule {} +export class UiSceneViewerTestModule {} diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts index c569b163..cf093c83 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.module.ts @@ -1,12 +1,12 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { SceneViewerComponent } from './scene-viewer.component'; -import { CameraFactory, EngineFactory, SceneViewerService } from './scene-viewer.service'; +import { UiSceneViewerComponent } from './scene-viewer.component'; +import { CameraFactory, EngineFactory, UiSceneViewerService } from './scene-viewer.service'; @NgModule({ - declarations: [SceneViewerComponent], + declarations: [UiSceneViewerComponent], imports: [CommonModule], - exports: [SceneViewerComponent], - providers: [CameraFactory, EngineFactory, SceneViewerService], + exports: [UiSceneViewerComponent], + providers: [CameraFactory, EngineFactory, UiSceneViewerService], }) -export class SceneViewerModule {} +export class UiSceneViewerModule {} diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index cf4d42fd..31960496 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -53,7 +53,7 @@ export class CameraFactory { * provided on module level. Therefore, only one `SceneViewerComponent` at the time is supported. */ @Injectable() -export class SceneViewerService { +export class UiSceneViewerService { pointerPick$ = new Subject(); private engine: Engine; diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts index 3d684bf3..19f3fa27 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts @@ -1,21 +1,23 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatSidenav } from '@angular/material'; +import { By } from '@angular/platform-browser'; -import { SidenavShellComponent } from './sidenav-shell.component'; -import { SidenavShellModule } from './sidenav-shell.module'; +import { UiSidenavShellComponent } from './sidenav-shell.component'; +import { UiSidenavShellModule } from './sidenav-shell.module'; describe('SidenavShellComponent', () => { - let component: SidenavShellComponent; - let fixture: ComponentFixture; + let component: UiSidenavShellComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [SidenavShellModule], + imports: [UiSidenavShellModule], declarations: [], }).compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(SidenavShellComponent); + fixture = TestBed.createComponent(UiSidenavShellComponent); component = fixture.componentInstance; fixture.detectChanges(); }); @@ -23,4 +25,14 @@ describe('SidenavShellComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should have left & right sidenav', () => { + const sidenavs = fixture.debugElement.queryAll(By.directive(MatSidenav)); + const leftSidenavIcon = fixture.debugElement.query(By.css('#left-sidenav-button mat-icon')); + const rightSidenavIcon = fixture.debugElement.query(By.css('#right-sidenav-button mat-icon')); + + expect(sidenavs.length).toEqual(2); + expect(leftSidenavIcon.nativeElement.textContent).toEqual('keyboard_arrow_left'); + expect(rightSidenavIcon.nativeElement.textContent).toEqual('keyboard_arrow_right'); + }); }); diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.ts b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.ts index bc22de2f..d4087cfa 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.ts +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'ui-sidenav-shell-content', @@ -7,7 +7,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SidenavShellContentComponent {} +export class UiSidenavShellContentComponent {} @Component({ selector: 'ui-sidenav-shell-left', @@ -16,7 +16,7 @@ export class SidenavShellContentComponent {} `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SidenavShellLeftComponent {} +export class UiSidenavShellLeftComponent {} @Component({ selector: 'ui-sidenav-shell-right', @@ -25,7 +25,7 @@ export class SidenavShellLeftComponent {} `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SidenavShellRightComponent {} +export class UiSidenavShellRightComponent {} @Component({ selector: 'ui-sidenav-shell', @@ -57,8 +57,4 @@ export class SidenavShellRightComponent {} styleUrls: ['./sidenav-shell.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SidenavShellComponent implements OnInit { - constructor() {} - - public ngOnInit(): void {} -} +export class UiSidenavShellComponent {} diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.module.ts b/libs/ui/src/lib/sidenav-shell/sidenav-shell.module.ts index 0486da5c..50a11df6 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.module.ts +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.module.ts @@ -3,18 +3,18 @@ import { NgModule } from '@angular/core'; import { MatButtonModule, MatIconModule, MatSidenavModule } from '@angular/material'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { - SidenavShellComponent, - SidenavShellContentComponent, - SidenavShellLeftComponent, - SidenavShellRightComponent, + UiSidenavShellComponent, + UiSidenavShellContentComponent, + UiSidenavShellLeftComponent, + UiSidenavShellRightComponent, } from './sidenav-shell.component'; @NgModule({ declarations: [ - SidenavShellComponent, - SidenavShellContentComponent, - SidenavShellLeftComponent, - SidenavShellRightComponent, + UiSidenavShellComponent, + UiSidenavShellContentComponent, + UiSidenavShellLeftComponent, + UiSidenavShellRightComponent, ], imports: [ BrowserAnimationsModule, @@ -24,10 +24,10 @@ import { MatSidenavModule, ], exports: [ - SidenavShellComponent, - SidenavShellContentComponent, - SidenavShellLeftComponent, - SidenavShellRightComponent, + UiSidenavShellComponent, + UiSidenavShellContentComponent, + UiSidenavShellLeftComponent, + UiSidenavShellRightComponent, ], }) -export class SidenavShellModule {} +export class UiSidenavShellModule {} diff --git a/libs/ui/src/lib/toolbar/toolbar.component.spec.ts b/libs/ui/src/lib/toolbar/toolbar.component.spec.ts index 3d0b3276..c422d2a4 100644 --- a/libs/ui/src/lib/toolbar/toolbar.component.spec.ts +++ b/libs/ui/src/lib/toolbar/toolbar.component.spec.ts @@ -1,19 +1,19 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ToolbarComponent } from './toolbar.component'; -import { ToolbarModule } from './toolbar.module'; +import { UiToolbarComponent } from './toolbar.component'; +import { UiToolbarModule } from './toolbar.module'; describe('ToolbarComponent', () => { - let component: ToolbarComponent; - let fixture: ComponentFixture; + let component: UiToolbarComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [ToolbarModule], + imports: [UiToolbarModule], }).compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(ToolbarComponent); + fixture = TestBed.createComponent(UiToolbarComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/libs/ui/src/lib/toolbar/toolbar.component.ts b/libs/ui/src/lib/toolbar/toolbar.component.ts index 68e2f341..d18e85c9 100644 --- a/libs/ui/src/lib/toolbar/toolbar.component.ts +++ b/libs/ui/src/lib/toolbar/toolbar.component.ts @@ -28,7 +28,7 @@ export interface UiToolbarToolChange extends MatButtonToggleChange { `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ToolbarComponent { +export class UiToolbarComponent { @Input() tools: UiToolbarToolConfig[]; @Input() selectedToolId: any; diff --git a/libs/ui/src/lib/toolbar/toolbar.module.ts b/libs/ui/src/lib/toolbar/toolbar.module.ts index 6e77b28c..5e5bbd0f 100644 --- a/libs/ui/src/lib/toolbar/toolbar.module.ts +++ b/libs/ui/src/lib/toolbar/toolbar.module.ts @@ -1,11 +1,11 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { MatButtonToggleModule, MatIconModule, MatTooltipModule } from '@angular/material'; -import { ToolbarComponent } from './toolbar.component'; +import { UiToolbarComponent } from './toolbar.component'; @NgModule({ - declarations: [ToolbarComponent], + declarations: [UiToolbarComponent], imports: [CommonModule, MatButtonToggleModule, MatIconModule, MatTooltipModule], - exports: [ToolbarComponent], + exports: [UiToolbarComponent], }) -export class ToolbarModule {} +export class UiToolbarModule {} diff --git a/libs/ui/tsconfig.spec.json b/libs/ui/tsconfig.spec.json index 61c376d5..29121926 100644 --- a/libs/ui/tsconfig.spec.json +++ b/libs/ui/tsconfig.spec.json @@ -4,6 +4,6 @@ "outDir": "../../dist/out-tsc", "types": ["jest", "node"] }, - "files": ["src/test-setup.ts"], + "files": ["./src/test-setup.ts"], "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/package.json b/package.json index 4b63e8b6..7925ad6b 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "@ngrx/effects": "8.6.0", "@ngrx/store": "8.6.0", "@nrwl/angular": "8.11.0", - "core-js": "3.6.4", "hammerjs": "2.0.8", "mnemonist": "0.32.0", "rxjs": "6.5.4", diff --git a/yarn.lock b/yarn.lock index adfc6408..46228c18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2347,11 +2347,16 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.4, acorn@^6.2.1: +acorn@^6.0.1, acorn@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== +acorn@^6.0.4: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + agent-base@4, agent-base@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" @@ -3828,11 +3833,6 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@3.6.4: - version "3.6.4" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" - integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw== - core-js@^2.4.0: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" @@ -4525,7 +4525,19 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.11.0, escodegen@^1.9.1: +escodegen@^1.11.0: + version "1.12.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" + integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@^1.9.1: version "1.12.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== From 4fe0e282757feec16728359759a46e04dbb4e51f Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 09:13:28 +0100 Subject: [PATCH 49/67] refactor(ui): prefix `UiPointer[Button|PickInfo]` with `Ui` --- .../scene-viewer-container.component.spec.ts | 10 +++++----- .../scene-viewer-container.component.ts | 14 +++++++------- libs/ui/src/lib/scene-viewer/index.ts | 4 ++-- libs/ui/src/lib/scene-viewer/pointer-button.ts | 2 +- .../src/lib/scene-viewer/scene-viewer.service.ts | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 931997cf..85a995e6 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { MemoizedSelector, Store } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; -import { PointerButton, PointerPickInfo } from '@talus/ui'; +import { UiPointerButton, UiPointerPickInfo } from '@talus/ui'; import { Coord } from '@talus/vdb'; import { Subject } from 'rxjs'; import * as fromApp from '../app.reducer'; @@ -18,7 +18,7 @@ import { SceneViewerContainerComponent } from './scene-viewer-container.componen changeDetection: ChangeDetectionStrategy.OnPush, }) class SceneViewerStubComponent { - @Output() pointerPick = new Subject(); + @Output() pointerPick = new Subject(); } describe('SceneViewerContainerComponent', () => { @@ -62,7 +62,7 @@ describe('SceneViewerContainerComponent', () => { it('should dispatch no action if not PointerButton.Main', () => { stubComponent.pointerPick.next({ pickedPoint: [0, 0, 0], - pointerButton: PointerButton.Secondary, + pointerButton: UiPointerButton.Secondary, normal: [0, 0, 0], }); @@ -119,7 +119,7 @@ describe('SceneViewerContainerComponent', () => { stubComponent.pointerPick.next({ pickedPoint, - pointerButton: PointerButton.Main, + pointerButton: UiPointerButton.Main, normal, }); @@ -175,7 +175,7 @@ describe('SceneViewerContainerComponent', () => { stubComponent.pointerPick.next({ pickedPoint, - pointerButton: PointerButton.Main, + pointerButton: UiPointerButton.Main, normal, }); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts index 9026d0b7..179cbf63 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.ts @@ -2,7 +2,7 @@ import { AfterViewInit, ChangeDetectionStrategy, Component, ViewChild } from '@a // import '@babylonjs/core/Rendering/edgesRenderer'; // import '@babylonjs/core/Rendering/outlineRenderer'; import { select, Store } from '@ngrx/store'; -import { PointerButton, PointerPickInfo, UiSceneViewerComponent } from '@talus/ui'; +import { UiPointerButton, UiPointerPickInfo, UiSceneViewerComponent } from '@talus/ui'; import { Coord } from '@talus/vdb'; import { Observable } from 'rxjs'; import * as fromApp from '../app.reducer'; @@ -32,7 +32,7 @@ export class SceneViewerContainerComponent implements AfterViewInit { this.store.dispatch(addVoxel({ position: [0, 0, 0], value: 42 })); } - onPointerPick(event: PointerPickInfo, selectedToolId: Tool): void { + onPointerPick(event: UiPointerPickInfo, selectedToolId: Tool): void { this.dispatchPickAction(event, selectedToolId); } @@ -41,8 +41,8 @@ export class SceneViewerContainerComponent implements AfterViewInit { // mesh.renderOutline = !mesh.renderOutline; // } - private dispatchPickAction(pickInfo: PointerPickInfo, selectedToolId: Tool): void { - if (pickInfo.pointerButton !== PointerButton.Main) { + private dispatchPickAction(pickInfo: UiPointerPickInfo, selectedToolId: Tool): void { + if (pickInfo.pointerButton !== UiPointerButton.Main) { return; } @@ -58,7 +58,7 @@ export class SceneViewerContainerComponent implements AfterViewInit { } } - private calcVoxelToAddPosition(pickInfo: PointerPickInfo): Coord { + private calcVoxelToAddPosition(pickInfo: UiPointerPickInfo): Coord { const pickedIntegerPoint = this.roundDimensionAlongNormal(pickInfo); // VDB removes fractional-part of the coordinate, i.e. 0.54 -> 0. @@ -80,7 +80,7 @@ export class SceneViewerContainerComponent implements AfterViewInit { return newPoint; } - private calcVoxelToRemovePosition(pickInfo: PointerPickInfo): Coord { + private calcVoxelToRemovePosition(pickInfo: UiPointerPickInfo): Coord { const pickedIntegerPoint = this.roundDimensionAlongNormal(pickInfo); const newPoint: Coord = [ @@ -107,7 +107,7 @@ export class SceneViewerContainerComponent implements AfterViewInit { * Since all the voxels are placed on integer positions the dimension of the picked point * needs to be rounded. */ - private roundDimensionAlongNormal(pickInfo: PointerPickInfo): Coord { + private roundDimensionAlongNormal(pickInfo: UiPointerPickInfo): Coord { return [ pickInfo.normal[0] !== 0 ? Math.round(pickInfo.pickedPoint[0]) : pickInfo.pickedPoint[0], pickInfo.normal[1] !== 0 ? Math.round(pickInfo.pickedPoint[1]) : pickInfo.pickedPoint[1], diff --git a/libs/ui/src/lib/scene-viewer/index.ts b/libs/ui/src/lib/scene-viewer/index.ts index 9e369a7f..7dfea1ff 100644 --- a/libs/ui/src/lib/scene-viewer/index.ts +++ b/libs/ui/src/lib/scene-viewer/index.ts @@ -1,5 +1,5 @@ export * from './scene-viewer.component'; export * from './scene-viewer.module'; export * from './scene-viewer.module.testing'; -export { PointerButton } from './pointer-button'; -export { PointerPickInfo, UiSceneViewerService } from './scene-viewer.service'; +export { UiPointerButton } from './pointer-button'; +export { UiPointerPickInfo, UiSceneViewerService } from './scene-viewer.service'; diff --git a/libs/ui/src/lib/scene-viewer/pointer-button.ts b/libs/ui/src/lib/scene-viewer/pointer-button.ts index 39afd4c3..f5ca1d33 100644 --- a/libs/ui/src/lib/scene-viewer/pointer-button.ts +++ b/libs/ui/src/lib/scene-viewer/pointer-button.ts @@ -1,7 +1,7 @@ /** * https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button#Syntax */ -export enum PointerButton { +export enum UiPointerButton { Main = 0, // usually the left button or the un-initialized state Auxiliary = 1, // usually the wheel button or the middle button (if present) Secondary = 2, // usually the right button diff --git a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts index 31960496..5dfeb749 100644 --- a/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts +++ b/libs/ui/src/lib/scene-viewer/scene-viewer.service.ts @@ -16,7 +16,7 @@ import '@babylonjs/core/Physics/physicsHelper'; // Needed for `onPointerPick` import { Scene } from '@babylonjs/core/scene'; import { Coord, MeshData } from '@talus/vdb'; import { Subject } from 'rxjs'; -import { PointerButton } from './pointer-button'; +import { UiPointerButton } from './pointer-button'; @Injectable() export class EngineFactory { @@ -54,7 +54,7 @@ export class CameraFactory { */ @Injectable() export class UiSceneViewerService { - pointerPick$ = new Subject(); + pointerPick$ = new Subject(); private engine: Engine; private scene: Scene; @@ -149,7 +149,7 @@ export class UiSceneViewerService { private registerPointerPick(): void { this.scene.onPointerPick = (event: PointerEvent, pickInfo: PickingInfo): void => { if (pickInfo.pickedMesh && pickInfo.pickedPoint) { - const info: PointerPickInfo = { + const info: UiPointerPickInfo = { pickedPoint: vector3ToCoord(pickInfo.pickedPoint), pointerButton: event.button, normal: this.getNormal(pickInfo.pickedMesh, pickInfo.faceId), @@ -191,8 +191,8 @@ function vector3ToCoord(vector: Vector3): Coord { return [vector.x, vector.y, vector.z]; } -export interface PointerPickInfo { +export interface UiPointerPickInfo { pickedPoint: Coord; - pointerButton: PointerButton; + pointerButton: UiPointerButton; normal: Coord; } From 6ecda72f1d2bc2969cf21876094189edbae72ea1 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 09:14:59 +0100 Subject: [PATCH 50/67] build(dep): update handlebars to `v4.7.2` due to security issues --- package.json | 1 + yarn.lock | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/package.json b/package.json index 7925ad6b..512b2fa6 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "cypress": "3.8.2", "dotenv": "8.2.0", "gh-pages": "2.2.0", + "handlebars": "4.7.2", "jasmine-marbles": "0.6.0", "jest": "24.9.0", "jest-junit": "10.0.0", diff --git a/yarn.lock b/yarn.lock index 46228c18..b8e310aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5403,6 +5403,17 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== +handlebars@4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7" + integrity sha512-4PwqDL2laXtTWZghzzCtunQUTLbo31pcCJrd/B/9JP8XbhVzpS5ZXuKqlOzsd1rtcaLo4KqAn8nl8mkknS4MHw== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + handlebars@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" From 98daf1f233f8653f4203fcde0ff9e0aeccd845e7 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 09:28:15 +0100 Subject: [PATCH 51/67] test(ui): should emit `value` of clicked menu items --- .../lib/menu-bar/menu-bar.component.spec.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts index 86f2eba4..c4121d55 100644 --- a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts @@ -48,6 +48,8 @@ describe('UiMenuBarComponent', () => { // Don't call `detectChanges()`, because of `OnPush` // See: https://github.com/angular/angular/issues/12313#issuecomment-301848232 // fixture.detectChanges(); + + spyOn(component.menuItemClick, 'emit'); }); it('should create', () => { @@ -86,4 +88,23 @@ describe('UiMenuBarComponent', () => { expect(menuItemButton.nativeElement.textContent).toEqual(expectedMenus[1].menuItems[j].label); }); }); + + it('should emit value of clicked menu items', () => { + component.menuConfig = { + menus: expectedMenus, + }; + fixture.detectChanges(); + + const menuButtons = fixture.debugElement.queryAll(By.css('button')); + menuButtons[1].nativeElement.click(); + fixture.detectChanges(); + + const menuItemButtons = fixture.debugElement.queryAll(By.css('button.mat-menu-item > span')); + + menuItemButtons[0].nativeElement.click(); + expect(component.menuItemClick.emit).toBeCalledWith('Value 2.1'); + + menuItemButtons[1].nativeElement.click(); + expect(component.menuItemClick.emit).toBeCalledWith('Value 2.2'); + }); }); From d286d109d67f4d63fe05cf78fac20c488d5dcc5e Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 09:53:38 +0100 Subject: [PATCH 52/67] test(ui): should emit on tool select --- .../src/lib/toolbar/toolbar.component.spec.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/libs/ui/src/lib/toolbar/toolbar.component.spec.ts b/libs/ui/src/lib/toolbar/toolbar.component.spec.ts index c422d2a4..c605ef2a 100644 --- a/libs/ui/src/lib/toolbar/toolbar.component.spec.ts +++ b/libs/ui/src/lib/toolbar/toolbar.component.spec.ts @@ -1,11 +1,25 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { UiToolbarComponent } from './toolbar.component'; +import { By } from '@angular/platform-browser'; +import { UiToolbarComponent, UiToolbarToolConfig } from './toolbar.component'; import { UiToolbarModule } from './toolbar.module'; describe('ToolbarComponent', () => { let component: UiToolbarComponent; let fixture: ComponentFixture; + const tools: UiToolbarToolConfig[] = [ + { + icon: 'add_circle_outline', + tooltip: 'Add', + value: 'Add test value', + }, + { + icon: 'remove_circle_outline', + tooltip: 'Remove', + value: 'Remove test value', + }, + ]; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [UiToolbarModule], @@ -15,10 +29,27 @@ describe('ToolbarComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(UiToolbarComponent); component = fixture.componentInstance; - fixture.detectChanges(); + // fixture.detectChanges(); + }); + + beforeEach(() => { + spyOn(component.toolChange, 'emit'); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should emit tool change', () => { + component.tools = tools; + fixture.detectChanges(); + + const buttonToggles = fixture.debugElement.queryAll(By.css('button.mat-button-toggle-button')); + expect(buttonToggles.length).toEqual(tools.length); + + buttonToggles[0].nativeElement.click(); + fixture.detectChanges(); + + expect(component.toolChange.emit).toHaveBeenCalled(); + }); }); From ca7f5f3d1a7ca628b2ad6ad2dfa2ce447279f6e0 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:08:31 +0100 Subject: [PATCH 53/67] test(ui): should close left & right sidenav --- .../sidenav-shell.component.spec.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts index 19f3fa27..464b0862 100644 --- a/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts +++ b/libs/ui/src/lib/sidenav-shell/sidenav-shell.component.spec.ts @@ -26,7 +26,7 @@ describe('SidenavShellComponent', () => { expect(component).toBeTruthy(); }); - it('should have left & right sidenav', () => { + it('should have open left & right sidenav', () => { const sidenavs = fixture.debugElement.queryAll(By.directive(MatSidenav)); const leftSidenavIcon = fixture.debugElement.query(By.css('#left-sidenav-button mat-icon')); const rightSidenavIcon = fixture.debugElement.query(By.css('#right-sidenav-button mat-icon')); @@ -35,4 +35,22 @@ describe('SidenavShellComponent', () => { expect(leftSidenavIcon.nativeElement.textContent).toEqual('keyboard_arrow_left'); expect(rightSidenavIcon.nativeElement.textContent).toEqual('keyboard_arrow_right'); }); + + it('should close left & right sidenav', () => { + // Close left sidenav + const leftSidenavButton = fixture.debugElement.query(By.css('#left-sidenav-button')); + leftSidenavButton.nativeElement.click(); + fixture.detectChanges(); + + const leftIconClosed = fixture.debugElement.query(By.css('#left-sidenav-button mat-icon')); + expect(leftIconClosed.nativeElement.textContent).toEqual('keyboard_arrow_right'); + + // Close right sidenav + const rightSidenavButton = fixture.debugElement.query(By.css('#right-sidenav-button')); + rightSidenavButton.nativeElement.click(); + fixture.detectChanges(); + + const rightIconClosed = fixture.debugElement.query(By.css('#right-sidenav-button mat-icon')); + expect(rightIconClosed.nativeElement.textContent).toEqual('keyboard_arrow_left'); + }); }); From d79568c331a5f94a035c63f6fc37e4aa5c7d05e6 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:17:38 +0100 Subject: [PATCH 54/67] test(frontend): should dispatch action --- .../menu-bar-container.component.spec.ts | 11 +++++++++++ .../scene-viewer-container.component.spec.ts | 5 ++++- libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts index d4ec9c9e..b8bc23ba 100644 --- a/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts +++ b/apps/frontend/src/app/menu-bar-container/menu-bar-container.component.spec.ts @@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Store, StoreModule } from '@ngrx/store'; import { MockStore } from '@ngrx/store/testing'; import { ROOT_REDUCERS, State } from '../app.reducer'; +import { undo } from './menu-bar-container.actions'; import { MenuBarContainerComponent } from './menu-bar-container.component'; import { MenuBarContainerModule } from './menu-bar-container.module'; @@ -30,6 +31,10 @@ describe('MenuBarComponent', () => { store = TestBed.get>(Store); })); + beforeEach(() => { + spyOn(store, 'dispatch'); + }); + beforeEach(() => { fixture = TestBed.createComponent(MenuBarContainerComponent); component = fixture.componentInstance; @@ -39,4 +44,10 @@ describe('MenuBarComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should dispatch action', () => { + component.onMenuItemClick(undo()); + + expect(store.dispatch).toHaveBeenCalledWith(undo()); + }); }); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts index 85a995e6..d3da561d 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.component.spec.ts @@ -36,7 +36,6 @@ describe('SceneViewerContainerComponent', () => { }).compileComponents(); mockStore = TestBed.get(Store); - spyOn(mockStore, 'dispatch'); mockSelectedToolIdSelector = mockStore.overrideSelector( fromApp.selectSelectedToolId, @@ -44,6 +43,10 @@ describe('SceneViewerContainerComponent', () => { ); })); + beforeEach(async(() => { + spyOn(mockStore, 'dispatch'); + })); + beforeEach(() => { fixture = TestBed.createComponent(SceneViewerContainerComponent); component = fixture.componentInstance; diff --git a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts index c4121d55..7f709fc2 100644 --- a/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts +++ b/libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts @@ -48,7 +48,9 @@ describe('UiMenuBarComponent', () => { // Don't call `detectChanges()`, because of `OnPush` // See: https://github.com/angular/angular/issues/12313#issuecomment-301848232 // fixture.detectChanges(); + }); + beforeEach(() => { spyOn(component.menuItemClick, 'emit'); }); From 8bcc6a2911809adc3d04131b9362779cf43fce75 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:29:04 +0100 Subject: [PATCH 55/67] test(frontend): check `scene-viewer-container.reducer` --- .../scene-viewer-container.reducer.spec.ts | 24 +++++++++++++++++++ .../scene-viewer-container.reducer.ts | 8 ++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts new file mode 100644 index 00000000..c276166b --- /dev/null +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts @@ -0,0 +1,24 @@ +import { VoxelChange } from './grid.service'; +import { voxelAdded, voxelRemoved } from './scene-viewer-container.actions'; +import { reducer } from './scene-viewer-container.reducer'; + +describe('SceneViewerContainerReducer', () => { + const voxelChange: VoxelChange = { + position: [0, 0, 0], + affectedNodeOrigin: [0, 0, 0], + value: 42, + }; + + it('should increment counter', () => { + const stateWithOneVoxel = reducer(undefined, voxelAdded(voxelChange)); + + expect(stateWithOneVoxel.voxelCount).toEqual(1); + }); + + it('should decrement counter', () => { + const stateWithOneVoxel = reducer(undefined, voxelAdded(voxelChange)); + const stateWithNoVoxel = reducer(stateWithOneVoxel, voxelRemoved(voxelChange)); + + expect(stateWithNoVoxel.voxelCount).toEqual(0); + }); +}); diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts index f89ac931..1b8ea98b 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.ts @@ -1,5 +1,5 @@ import { createReducer, on } from '@ngrx/store'; -import { voxelAdded } from './scene-viewer-container.actions'; +import { voxelAdded, voxelRemoved } from './scene-viewer-container.actions'; export const featureKey = 'sceneViewerContainer'; @@ -19,6 +19,12 @@ export const reducer = createReducer( voxelCount: state.voxelCount + 1, }; }), + on(voxelRemoved, state => { + return { + ...state, + voxelCount: state.voxelCount - 1, + }; + }), ); export const selectVoxelCount = (state: State) => state.voxelCount; From d81644ec263ce3a9c56509a673d851112808a735 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:36:16 +0100 Subject: [PATCH 56/67] test(frontend): check `scene-viewer-container.reducer` selector --- .../scene-viewer-container.reducer.spec.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts index c276166b..b8f51290 100644 --- a/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts +++ b/apps/frontend/src/app/scene-viewer-container/scene-viewer-container.reducer.spec.ts @@ -1,6 +1,6 @@ import { VoxelChange } from './grid.service'; import { voxelAdded, voxelRemoved } from './scene-viewer-container.actions'; -import { reducer } from './scene-viewer-container.reducer'; +import { reducer, selectVoxelCount } from './scene-viewer-container.reducer'; describe('SceneViewerContainerReducer', () => { const voxelChange: VoxelChange = { @@ -21,4 +21,10 @@ describe('SceneViewerContainerReducer', () => { expect(stateWithNoVoxel.voxelCount).toEqual(0); }); + + it('should select voxel count', () => { + const stateWithOneVoxel = reducer(undefined, voxelAdded(voxelChange)); + + expect(selectVoxelCount(stateWithOneVoxel)).toEqual(1); + }); }); From c2dadc9cc8a1835e4e77b7baf233ba060ed84046 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:38:03 +0100 Subject: [PATCH 57/67] refactor(ui): import `hammerjs` to remove warning in test run --- libs/ui/src/test-setup.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ui/src/test-setup.ts b/libs/ui/src/test-setup.ts index 8d88704e..26ec1bb0 100644 --- a/libs/ui/src/test-setup.ts +++ b/libs/ui/src/test-setup.ts @@ -1 +1,2 @@ +import 'hammerjs'; import 'jest-preset-angular'; From 2677de4722f78617c72f3c355f7f9a0e476bc650 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 10:45:19 +0100 Subject: [PATCH 58/67] test(frontend): check `tools-panel.reducer` --- .../src/app/tools-panel/tools-panel.reducer.spec.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 apps/frontend/src/app/tools-panel/tools-panel.reducer.spec.ts diff --git a/apps/frontend/src/app/tools-panel/tools-panel.reducer.spec.ts b/apps/frontend/src/app/tools-panel/tools-panel.reducer.spec.ts new file mode 100644 index 00000000..48409661 --- /dev/null +++ b/apps/frontend/src/app/tools-panel/tools-panel.reducer.spec.ts @@ -0,0 +1,11 @@ +import { Tool } from './tool.model'; +import { selectTool } from './tools-panel.actions'; +import { reducer } from './tools-panel.reducer'; + +describe('ToolsPanelReducer', () => { + it('should set selected tool', () => { + const newState = reducer(undefined, selectTool({ id: Tool.AddVoxel })); + + expect(newState.selectedToolId).toEqual(Tool.AddVoxel); + }); +}); From 4ea47f5b516901ea951340cbf5e48172870bda88 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 11:12:06 +0100 Subject: [PATCH 59/67] test(frontend): check `undo-redo.reducer` --- .../src/app/undo-redo/undo-redo.effects.ts | 23 +--- .../app/undo-redo/undo-redo.reducer.spec.ts | 104 ++++++++++++++++++ 2 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts diff --git a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts index 82ce29c0..4bafbe85 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.effects.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.effects.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { Action, select, Store } from '@ngrx/store'; +import { select, Store } from '@ngrx/store'; import { filter, map, switchMap, withLatestFrom } from 'rxjs/operators'; import * as fromApp from '../app.reducer'; import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions'; @@ -75,13 +75,11 @@ export class UndoRedoEffects { ofType(voxelAdded), map(voxelChange => ({ redoStartAction: addVoxel(voxelChange), - redoEndAction: voxelAdded.type, + redoEndActionType: voxelAdded.type, undoStartAction: removeVoxel({ position: voxelChange.position }), undoEndActionType: voxelRemoved.type, })), - map(({ redoStartAction, redoEndAction, undoStartAction, undoEndActionType }) => - this.createAddUndo(redoStartAction, redoEndAction, undoStartAction, undoEndActionType), - ), + map(addUndo), ), ); @@ -90,22 +88,11 @@ export class UndoRedoEffects { ofType(voxelRemoved), map(voxelChange => ({ redoStartAction: removeVoxel({ position: voxelChange.position }), - redoEndAction: voxelRemoved.type, + redoEndActionType: voxelRemoved.type, undoStartAction: addVoxel(voxelChange), undoEndActionType: voxelAdded.type, })), - map(({ redoStartAction, redoEndAction, undoStartAction, undoEndActionType }) => - this.createAddUndo(redoStartAction, redoEndAction, undoStartAction, undoEndActionType), - ), + map(addUndo), ), ); - - createAddUndo( - redoStartAction: Action, - redoEndActionType: string, - undoStartAction: Action, - undoEndActionType: string, - ): Action { - return addUndo({ redoStartAction, redoEndActionType, undoStartAction, undoEndActionType }); - } } diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts new file mode 100644 index 00000000..6e1a0c5a --- /dev/null +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts @@ -0,0 +1,104 @@ +import { VoxelChange } from '../scene-viewer-container/grid.service'; +import { addVoxel, removeVoxel, voxelAdded, voxelRemoved } from '../scene-viewer-container/scene-viewer-container.actions'; +import { addUndo, redo, undo, undone } from './undo-redo.actions'; +import { + reducer, + selectCurrentRedoEndAction, + selectCurrentRedoStartAction, + selectCurrentUndoEndAction, + selectCurrentUndoStartAction, +} from './undo-redo.reducer'; + +describe('UndoRedoReducer', () => { + const voxelChange: VoxelChange = { + position: [0, 0, 0], + affectedNodeOrigin: [0, 0, 0], + value: 42, + }; + const lastVoxelChange: VoxelChange = { + position: [1, 1, 1], + affectedNodeOrigin: [1, 1, 1], + value: 24, + }; + const undoStep = { + redoStartAction: addVoxel(voxelChange), + redoEndActionType: voxelAdded.type, + undoStartAction: removeVoxel({ position: voxelChange.position }), + undoEndActionType: voxelRemoved.type, + }; + const lastUndoStep = { + redoStartAction: addVoxel(lastVoxelChange), + redoEndActionType: voxelAdded.type, + undoStartAction: removeVoxel({ position: lastVoxelChange.position }), + undoEndActionType: voxelRemoved.type, + }; + + it('should be undoing', () => { + const newState = reducer(undefined, undo()); + + expect(newState.isUndoing).toEqual(true); + }); + + it('should be redoing', () => { + const newState = reducer(undefined, redo()); + + expect(newState.isRedoing).toEqual(true); + }); + + it('should add undo step', () => { + let newState = reducer(undefined, addUndo(undoStep)); + newState = reducer(newState, addUndo(undoStep)); + newState = reducer(newState, addUndo(undoStep)); + + expect(newState.redoStartActions.length).toEqual(3); + expect(newState.redoEndActionTypes.length).toEqual(3); + expect(newState.undoStartActions.length).toEqual(3); + expect(newState.undoEndActionTypes.length).toEqual(3); + }); + + it('should update current index', () => { + let newState = reducer(undefined, addUndo(undoStep)); + newState = reducer(newState, addUndo(undoStep)); + newState = reducer(newState, addUndo(lastUndoStep)); + + expect(newState.currentIndex).toEqual(2); + expect(newState.redoEndActionTypes.length).toEqual(3); + expect(newState.undoStartActions.length).toEqual(3); + expect(newState.undoEndActionTypes.length).toEqual(3); + + expect(selectCurrentUndoStartAction(newState)).toEqual(lastUndoStep.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(lastUndoStep.undoEndActionType); + expect(selectCurrentRedoStartAction(newState)).toBeUndefined(); + expect(selectCurrentRedoEndAction(newState)).toBeUndefined(); + }); + + it('should select current undo/redo', () => { + let newState = reducer(undefined, addUndo(undoStep)); + newState = reducer(newState, addUndo(undoStep)); + newState = reducer(newState, addUndo(lastUndoStep)); + + expect(selectCurrentUndoStartAction(newState)).toEqual(lastUndoStep.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(lastUndoStep.undoEndActionType); + expect(selectCurrentRedoStartAction(newState)).toBeUndefined(); + expect(selectCurrentRedoEndAction(newState)).toBeUndefined(); + }); + + it('should select current undo/redo after one undone', () => { + let newState = reducer(undefined, addUndo(undoStep)); + newState = reducer(newState, addUndo(undoStep)); + newState = reducer(newState, addUndo(lastUndoStep)); + newState = reducer(newState, undone()); + + expect(newState.currentIndex).toEqual(1); + + expect(newState.redoStartActions.length).toEqual(3); + expect(newState.redoEndActionTypes.length).toEqual(3); + expect(newState.undoStartActions.length).toEqual(3); + expect(newState.undoEndActionTypes.length).toEqual(3); + + expect(selectCurrentUndoStartAction(newState)).toEqual(undoStep.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(undoStep.undoEndActionType); + expect(selectCurrentRedoStartAction(newState)).toEqual(lastUndoStep.redoStartAction); + expect(selectCurrentRedoEndAction(newState)).toEqual(lastUndoStep.redoEndActionType); + }); +}); From dffd51f3d64cb0eb11dd66cb61dc08e2834e48f6 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 11:29:43 +0100 Subject: [PATCH 60/67] test(frontend): check `undo-redo.reducer` with `stepX` --- .../app/undo-redo/undo-redo.reducer.spec.ts | 145 +++++++++++------- 1 file changed, 86 insertions(+), 59 deletions(-) diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts index 6e1a0c5a..e8328892 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts @@ -1,37 +1,29 @@ +import { Action } from '@ngrx/store'; +import { Coord } from '@talus/vdb'; import { VoxelChange } from '../scene-viewer-container/grid.service'; -import { addVoxel, removeVoxel, voxelAdded, voxelRemoved } from '../scene-viewer-container/scene-viewer-container.actions'; -import { addUndo, redo, undo, undone } from './undo-redo.actions'; +import { + addVoxel, + removeVoxel, + voxelAdded, + voxelRemoved, +} from '../scene-viewer-container/scene-viewer-container.actions'; +import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; import { reducer, selectCurrentRedoEndAction, selectCurrentRedoStartAction, selectCurrentUndoEndAction, selectCurrentUndoStartAction, + State, } from './undo-redo.reducer'; describe('UndoRedoReducer', () => { - const voxelChange: VoxelChange = { - position: [0, 0, 0], - affectedNodeOrigin: [0, 0, 0], - value: 42, - }; - const lastVoxelChange: VoxelChange = { - position: [1, 1, 1], - affectedNodeOrigin: [1, 1, 1], - value: 24, - }; - const undoStep = { - redoStartAction: addVoxel(voxelChange), - redoEndActionType: voxelAdded.type, - undoStartAction: removeVoxel({ position: voxelChange.position }), - undoEndActionType: voxelRemoved.type, - }; - const lastUndoStep = { - redoStartAction: addVoxel(lastVoxelChange), - redoEndActionType: voxelAdded.type, - undoStartAction: removeVoxel({ position: lastVoxelChange.position }), - undoEndActionType: voxelRemoved.type, - }; + const voxelChange0 = createVoxelChange([0, 0, 0]); + const step0 = createStep(voxelChange0); + const voxelChange1 = createVoxelChange([1, 1, 1]); + const step1 = createStep(voxelChange1); + const voxelChange2 = createVoxelChange([2, 2, 2]); + const step2 = createStep(voxelChange2); it('should be undoing', () => { const newState = reducer(undefined, undo()); @@ -46,59 +38,94 @@ describe('UndoRedoReducer', () => { }); it('should add undo step', () => { - let newState = reducer(undefined, addUndo(undoStep)); - newState = reducer(newState, addUndo(undoStep)); - newState = reducer(newState, addUndo(undoStep)); - - expect(newState.redoStartActions.length).toEqual(3); - expect(newState.redoEndActionTypes.length).toEqual(3); - expect(newState.undoStartActions.length).toEqual(3); - expect(newState.undoEndActionTypes.length).toEqual(3); + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + + expectActionLengthToEqual(newState, 3); }); it('should update current index', () => { - let newState = reducer(undefined, addUndo(undoStep)); - newState = reducer(newState, addUndo(undoStep)); - newState = reducer(newState, addUndo(lastUndoStep)); + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); expect(newState.currentIndex).toEqual(2); - expect(newState.redoEndActionTypes.length).toEqual(3); - expect(newState.undoStartActions.length).toEqual(3); - expect(newState.undoEndActionTypes.length).toEqual(3); - - expect(selectCurrentUndoStartAction(newState)).toEqual(lastUndoStep.undoStartAction); - expect(selectCurrentUndoEndAction(newState)).toEqual(lastUndoStep.undoEndActionType); - expect(selectCurrentRedoStartAction(newState)).toBeUndefined(); - expect(selectCurrentRedoEndAction(newState)).toBeUndefined(); + expectActionLengthToEqual(newState, 3); }); it('should select current undo/redo', () => { - let newState = reducer(undefined, addUndo(undoStep)); - newState = reducer(newState, addUndo(undoStep)); - newState = reducer(newState, addUndo(lastUndoStep)); + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); - expect(selectCurrentUndoStartAction(newState)).toEqual(lastUndoStep.undoStartAction); - expect(selectCurrentUndoEndAction(newState)).toEqual(lastUndoStep.undoEndActionType); + expect(selectCurrentUndoStartAction(newState)).toEqual(step2.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(step2.undoEndActionType); expect(selectCurrentRedoStartAction(newState)).toBeUndefined(); expect(selectCurrentRedoEndAction(newState)).toBeUndefined(); }); it('should select current undo/redo after one undone', () => { - let newState = reducer(undefined, addUndo(undoStep)); - newState = reducer(newState, addUndo(undoStep)); - newState = reducer(newState, addUndo(lastUndoStep)); + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); newState = reducer(newState, undone()); expect(newState.currentIndex).toEqual(1); + expectActionLengthToEqual(newState, 3); + + expect(selectCurrentUndoStartAction(newState)).toEqual(step1.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(step1.undoEndActionType); + expect(selectCurrentRedoStartAction(newState)).toEqual(step2.redoStartAction); + expect(selectCurrentRedoEndAction(newState)).toEqual(step2.redoEndActionType); + }); + + it('should select current undo/redo after three undone & one redo', () => { + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, redone()); - expect(newState.redoStartActions.length).toEqual(3); - expect(newState.redoEndActionTypes.length).toEqual(3); - expect(newState.undoStartActions.length).toEqual(3); - expect(newState.undoEndActionTypes.length).toEqual(3); + expect(newState.currentIndex).toEqual(0); + expectActionLengthToEqual(newState, 3); - expect(selectCurrentUndoStartAction(newState)).toEqual(undoStep.undoStartAction); - expect(selectCurrentUndoEndAction(newState)).toEqual(undoStep.undoEndActionType); - expect(selectCurrentRedoStartAction(newState)).toEqual(lastUndoStep.redoStartAction); - expect(selectCurrentRedoEndAction(newState)).toEqual(lastUndoStep.redoEndActionType); + expect(selectCurrentUndoStartAction(newState)).toEqual(step0.undoStartAction); + expect(selectCurrentUndoEndAction(newState)).toEqual(step0.undoEndActionType); + expect(selectCurrentRedoStartAction(newState)).toEqual(step1.redoStartAction); + expect(selectCurrentRedoEndAction(newState)).toEqual(step1.redoEndActionType); }); }); + +function createVoxelChange(xyz: Coord): VoxelChange { + return { + position: xyz, + affectedNodeOrigin: xyz, + value: 42, + }; +} + +function createStep( + voxelChange: VoxelChange, +): { + redoEndActionType: string; + redoStartAction: Action; + undoEndActionType: string; + undoStartAction: Action; +} { + return { + redoStartAction: addVoxel(voxelChange), + redoEndActionType: voxelAdded.type, + undoStartAction: removeVoxel({ position: voxelChange.position }), + undoEndActionType: voxelRemoved.type, + }; +} + +function expectActionLengthToEqual(state: State, length: number): void { + expect(state.redoStartActions.length).toEqual(length); + expect(state.redoEndActionTypes.length).toEqual(length); + expect(state.undoStartActions.length).toEqual(length); + expect(state.undoEndActionTypes.length).toEqual(length); +} From 43a35520059ff07ffc5c52df18e4612460c4998a Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 11:42:17 +0100 Subject: [PATCH 61/67] test(frontend): check `undo-redo.reducer` too many undo/redo's --- .../app/undo-redo/undo-redo.reducer.spec.ts | 75 +++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts index e8328892..39a2d7d7 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts @@ -1,12 +1,7 @@ import { Action } from '@ngrx/store'; import { Coord } from '@talus/vdb'; import { VoxelChange } from '../scene-viewer-container/grid.service'; -import { - addVoxel, - removeVoxel, - voxelAdded, - voxelRemoved, -} from '../scene-viewer-container/scene-viewer-container.actions'; +import { addVoxel, removeVoxel, voxelAdded, voxelRemoved } from '../scene-viewer-container/scene-viewer-container.actions'; import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; import { reducer, @@ -97,6 +92,74 @@ describe('UndoRedoReducer', () => { expect(selectCurrentRedoStartAction(newState)).toEqual(step1.redoStartAction); expect(selectCurrentRedoEndAction(newState)).toEqual(step1.redoEndActionType); }); + + it('should consider max buffer size of 10', () => { + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, addUndo(step0)); + + newState = reducer(newState, addUndo(step1)); + + expect(newState.currentIndex).toEqual(9); + expectActionLengthToEqual(newState, 10); + }); + + it('should remove history', () => { + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step0)); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, addUndo(step2)); + + expect(newState.currentIndex).toEqual(4); + expectActionLengthToEqual(newState, 5); + }); + + it('should stop decrement index after too many undo', () => { + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + + newState = reducer(newState, undone()); + + expect(newState.currentIndex).toEqual(-1); + expectActionLengthToEqual(newState, 3); + }); + + it('should stop increment index after too many redo', () => { + let newState = reducer(undefined, addUndo(step0)); + newState = reducer(newState, addUndo(step1)); + newState = reducer(newState, addUndo(step2)); + newState = reducer(newState, undone()); + newState = reducer(newState, undone()); + newState = reducer(newState, redone()); + newState = reducer(newState, redone()); + + newState = reducer(newState, redone()); + + expect(newState.currentIndex).toEqual(2); + expectActionLengthToEqual(newState, 3); + }); }); function createVoxelChange(xyz: Coord): VoxelChange { From 7d44795027e8a766c201f720d4129af5d5fc2041 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 11:56:54 +0100 Subject: [PATCH 62/67] style(prettier): fix imports --- apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts index 39a2d7d7..61afc316 100644 --- a/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts +++ b/apps/frontend/src/app/undo-redo/undo-redo.reducer.spec.ts @@ -1,7 +1,12 @@ import { Action } from '@ngrx/store'; import { Coord } from '@talus/vdb'; import { VoxelChange } from '../scene-viewer-container/grid.service'; -import { addVoxel, removeVoxel, voxelAdded, voxelRemoved } from '../scene-viewer-container/scene-viewer-container.actions'; +import { + addVoxel, + removeVoxel, + voxelAdded, + voxelRemoved, +} from '../scene-viewer-container/scene-viewer-container.actions'; import { addUndo, redo, redone, undo, undone } from './undo-redo.actions'; import { reducer, From bf1a295335440bfbf11a3d3f53671e703ef5a4e1 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 13:17:16 +0100 Subject: [PATCH 63/67] test(vdb): add tests for `tree` --- libs/vdb/src/lib/tree/tree.spec.ts | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 libs/vdb/src/lib/tree/tree.spec.ts diff --git a/libs/vdb/src/lib/tree/tree.spec.ts b/libs/vdb/src/lib/tree/tree.spec.ts new file mode 100644 index 00000000..6e86aa4f --- /dev/null +++ b/libs/vdb/src/lib/tree/tree.spec.ts @@ -0,0 +1,51 @@ +import { Tree } from './tree'; + +describe('Tree', () => { + it('should get background', () => { + const tree = new Tree(-1); + + expect(tree.background).toEqual(-1); + }); + + it('should get/set value', () => { + const tree = new Tree(-1); + + tree.setValueOn([0, 1, 2], 42); + + expect(tree.getValue([0, 1, 2])).toEqual(42); + }); + + it('should activated value', () => { + const tree = new Tree(-1); + + tree.setValueOn([0, 1, 2], 42); + + expect(tree.isValueOn([0, 1, 2])).toBeTruthy(); + }); + + it('should count voxel', () => { + const tree = new Tree(-1); + + tree.setValueOn([0, 1, 2], 42); + tree.setValueOn([845, 242, 64], 42); + tree.setValueOn([1000, 4000, 200000], 42); + + expect(tree.onVoxelCount()).toEqual(3); + }); + + it('should iterate over each activated voxel', () => { + const tree = new Tree(-1); + + tree.setValueOn([0, 1, 2], 42); + tree.setValueOn([845, 242, 64], 42); + tree.setValueOn([1000, 4000, 200000], 42); + + let counter = 0; + for (const voxel of tree.beginVoxelOn()) { + counter++; + expect(voxel.value).toEqual(42); + } + + expect(counter).toEqual(3); + }); +}); From e7e93c84b4d1f23bd83d3881736cb2070bb18873 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 14:02:24 +0100 Subject: [PATCH 64/67] test(vdb): improve coverage --- apps/benchmark/src/app/vdb/grid.benchmark.ts | 2 +- .../scene-viewer-container/grid.service.ts | 2 +- libs/vdb/src/lib/tools/node-to-mesh.spec.ts | 4 +- libs/vdb/src/lib/tree/root-node.spec.ts | 138 +++++++++--------- libs/vdb/src/lib/tree/value-accessor.spec.ts | 52 ++++++- libs/vdb/src/lib/tree/value-accessor.ts | 5 +- 6 files changed, 122 insertions(+), 81 deletions(-) diff --git a/apps/benchmark/src/app/vdb/grid.benchmark.ts b/apps/benchmark/src/app/vdb/grid.benchmark.ts index 94e46c7c..6cde5004 100644 --- a/apps/benchmark/src/app/vdb/grid.benchmark.ts +++ b/apps/benchmark/src/app/vdb/grid.benchmark.ts @@ -46,7 +46,7 @@ suite('[Grid] setValue()', () => { for (let x = 0; x < i; x++) { for (let y = 0; y < i; y++) { for (let z = 0; z < i; z++) { - accessor.setValue([x, y, z], i); + accessor.setValueOn([x, y, z], i); } } } diff --git a/apps/frontend/src/app/scene-viewer-container/grid.service.ts b/apps/frontend/src/app/scene-viewer-container/grid.service.ts index 0007160c..4fda072e 100644 --- a/apps/frontend/src/app/scene-viewer-container/grid.service.ts +++ b/apps/frontend/src/app/scene-viewer-container/grid.service.ts @@ -28,7 +28,7 @@ export class GridService { * @returns origin of `InternalNode1` of affected node (node containing added voxel). */ addVoxel(xyz: Coord, value: number): VoxelChange { - this.accessor.setValue(xyz, value); + this.accessor.setValueOn(xyz, value); return { affectedNodeOrigin: this.accessor.internalNode1Origin, diff --git a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts index 4ac01600..0b0ae6e2 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts @@ -6,8 +6,8 @@ describe('nodeToMesh()', () => { const grid = new Grid(0); const accessor = grid.getAccessor(); - accessor.setValue([0, 0, 0], 1); - accessor.setValue([0, 0, 1], 1); + accessor.setValueOn([0, 0, 0], 1); + accessor.setValueOn([0, 0, 1], 1); const meshData = nodeToMesh(grid.tree.root, () => [0, 0, 0, 1]); diff --git a/libs/vdb/src/lib/tree/root-node.spec.ts b/libs/vdb/src/lib/tree/root-node.spec.ts index 6ee42d90..47b1d179 100644 --- a/libs/vdb/src/lib/tree/root-node.spec.ts +++ b/libs/vdb/src/lib/tree/root-node.spec.ts @@ -2,95 +2,93 @@ import { InternalNode2 } from './internal-node'; import { RootNode } from './root-node'; describe('RootNode', () => { - describe('setValueOn()', () => { - it('should set given value and activate it', () => { - const root = new RootNode(-1); + it('should set given value and activate it', () => { + const root = new RootNode(-1); - root.setValueOn([0, 0, 0], 24); - root.setValueOn([102, 15, 127], 42); + root.setValueOn([0, 0, 0], 24); + root.setValueOn([102, 15, 127], 42); - expect(root.getValue([0, 0, 0])).toEqual(24); - expect(root.getValue([102, 15, 127])).toEqual(42); + expect(root.getValue([0, 0, 0])).toEqual(24); + expect(root.getValue([102, 15, 127])).toEqual(42); - expect(root.isValueOn([0, 0, 0])).toEqual(true); - expect(root.isValueOn([102, 15, 127])).toEqual(true); + expect(root.isValueOn([0, 0, 0])).toEqual(true); + expect(root.isValueOn([102, 15, 127])).toEqual(true); - expect(root.getValue([1, 1, 1])).toEqual(-1); - }); + expect(root.getValue([1, 1, 1])).toEqual(-1); + }); + + it('should return background', () => { + const root = new RootNode(-1); + + expect(root.getValue([111, 222, 333])).toEqual(-1); + }); - it('should set value when given float coordinates', () => { - const root = new RootNode(-1); + it('should set value when given float coordinates', () => { + const root = new RootNode(-1); - root.setValueOn([0, 0, 0.1], 1); - root.setValueOn([0, 1.5, 0], 5); - root.setValueOn([2.9, 0, 0], 9); + root.setValueOn([0, 0, 0.1], 1); + root.setValueOn([0, 1.5, 0], 5); + root.setValueOn([2.9, 0, 0], 9); - expect(root.getValue([0, 0, 0])).toEqual(1); - expect(root.getValue([0, 0, 1])).toEqual(-1); - expect(root.getValue([0, 1, 0])).toEqual(5); - expect(root.getValue([0, 2, 0])).toEqual(-1); - expect(root.getValue([2, 0, 0])).toEqual(9); - expect(root.getValue([3, 0, 0])).toEqual(-1); + expect(root.getValue([0, 0, 0])).toEqual(1); + expect(root.getValue([0, 0, 1])).toEqual(-1); + expect(root.getValue([0, 1, 0])).toEqual(5); + expect(root.getValue([0, 2, 0])).toEqual(-1); + expect(root.getValue([2, 0, 0])).toEqual(9); + expect(root.getValue([3, 0, 0])).toEqual(-1); - root.setValueOn([0, 0, -1.2], -2); - root.setValueOn([0, -2.5, 0], -5); - root.setValueOn([-3.9, 0, 0], -9); + root.setValueOn([0, 0, -1.2], -2); + root.setValueOn([0, -2.5, 0], -5); + root.setValueOn([-3.9, 0, 0], -9); - expect(root.getValue([0, 0, -1])).toEqual(-2); - expect(root.getValue([0, -2, 0])).toEqual(-5); - expect(root.getValue([-3, 0, 0])).toEqual(-9); - }); + expect(root.getValue([0, 0, -1])).toEqual(-2); + expect(root.getValue([0, -2, 0])).toEqual(-5); + expect(root.getValue([-3, 0, 0])).toEqual(-9); }); - describe('onVoxelCount()', () => { - it('should count all activated voxels', () => { - const root = new RootNode(-1); + it('should count all activated voxels', () => { + const root = new RootNode(-1); - root.setValueOn([0, 0, 0], 24); - root.setValueOn([102, 15, 127], 42); + root.setValueOn([0, 0, 0], 24); + root.setValueOn([102, 15, 127], 42); - expect(root.onVoxelCount()).toEqual(2); - }); + expect(root.onVoxelCount()).toEqual(2); }); - describe('getTableSize()', () => { - it('should create new entries when inserting values', () => { - const root = new RootNode(-1); - - root.setValueOn([0, 0, 0], 24); - root.setValueOn([0, 0, 1], 24); - root.setValueOn([102, 15, 127], 42); - expect(root.getTableSize()).toEqual(1); - - root.setValueOn([0, 0, InternalNode2.DIM], 42); - root.setValueOn([0, 1, InternalNode2.DIM], 42); - root.setValueOn([1, 0, InternalNode2.DIM], 42); - expect(root.getTableSize()).toEqual(2); - - root.setValueOn([InternalNode2.DIM, 0, 0], 42); - root.setValueOn([InternalNode2.DIM, 0, 1], 42); - root.setValueOn([InternalNode2.DIM, 1, 0], 42); - expect(root.getTableSize()).toEqual(3); - }); + it('should create new entries when inserting values', () => { + const root = new RootNode(-1); + + root.setValueOn([0, 0, 0], 24); + root.setValueOn([0, 0, 1], 24); + root.setValueOn([102, 15, 127], 42); + expect(root.getTableSize()).toEqual(1); + + root.setValueOn([0, 0, InternalNode2.DIM], 42); + root.setValueOn([0, 1, InternalNode2.DIM], 42); + root.setValueOn([1, 0, InternalNode2.DIM], 42); + expect(root.getTableSize()).toEqual(2); + + root.setValueOn([InternalNode2.DIM, 0, 0], 42); + root.setValueOn([InternalNode2.DIM, 0, 1], 42); + root.setValueOn([InternalNode2.DIM, 1, 0], 42); + expect(root.getTableSize()).toEqual(3); }); - describe('beginVoxelOn()', () => { - it('should iterate over all activated voxels', () => { - const root = new RootNode(-1); - const expectedValues = [0, 1, 2, 3]; + it('should iterate over all activated voxels', () => { + const root = new RootNode(-1); + const expectedValues = [0, 1, 2, 3]; - root.setValueOn([0, 0, 0], expectedValues[0]); - root.setValueOn([0, 0, InternalNode2.DIM], expectedValues[1]); - root.setValueOn([0, InternalNode2.DIM, 0], expectedValues[2]); - root.setValueOn([InternalNode2.DIM, 0, 0], expectedValues[3]); + root.setValueOn([0, 0, 0], expectedValues[0]); + root.setValueOn([0, 0, InternalNode2.DIM], expectedValues[1]); + root.setValueOn([0, InternalNode2.DIM, 0], expectedValues[2]); + root.setValueOn([InternalNode2.DIM, 0, 0], expectedValues[3]); - let counter = 0; - for (const voxel of root.beginVoxelOn()) { - expect(voxel.value).toEqual(expectedValues[counter]); - counter++; - } + let counter = 0; + for (const voxel of root.beginVoxelOn()) { + expect(voxel.value).toEqual(expectedValues[counter]); + counter++; + } - expect(counter).toEqual(expectedValues.length); - }); + expect(counter).toEqual(expectedValues.length); }); }); diff --git a/libs/vdb/src/lib/tree/value-accessor.spec.ts b/libs/vdb/src/lib/tree/value-accessor.spec.ts index d110c44e..8398e31b 100644 --- a/libs/vdb/src/lib/tree/value-accessor.spec.ts +++ b/libs/vdb/src/lib/tree/value-accessor.spec.ts @@ -1,8 +1,16 @@ -import { InternalNode2 } from './internal-node'; +import { LeafNode } from '@talus/vdb'; +import { InternalNode1, InternalNode2 } from './internal-node'; import { Tree } from './tree'; import { ValueAccessor3 } from './value-accessor'; describe('ValueAccessor', () => { + it('should return background', () => { + const tree = new Tree(-1); + const accessor = new ValueAccessor3(tree); + + expect(accessor.getValue([111, 222, 333])).toEqual(-1); + }); + describe('getValue()', () => { it('should cache coordinate', () => { const tree = new Tree(0); @@ -22,12 +30,12 @@ describe('ValueAccessor', () => { }); }); - describe('setValue()', () => { + describe('setValueOn()', () => { it('should cache coordinate', () => { const tree = new Tree(0); const accessor = new ValueAccessor3(tree); - accessor.setValue([0, 0, 0], 1496); + accessor.setValueOn([0, 0, 0], 1496); const value = accessor.getValue([0, 0, 0]); expect(value).toEqual(1496); @@ -103,4 +111,42 @@ describe('ValueAccessor', () => { expect(accessor.isValueOn([0, 0, 1])).toBeFalsy(); }); }); + + describe('probeInternalNode1()', () => { + const tree = new Tree(-1); + + it('should return undefined if no internal node 1', () => { + const accessor = new ValueAccessor3(tree); + + expect(accessor.probeInternalNode1([111, 222, 333])).toBeUndefined(); + }); + + it('should hit no cache and return internal node 1', () => { + const accessor = new ValueAccessor3(tree); + + accessor.setValueOn([0, 0, 0], 42); + // Produce a cache miss (go over root) + accessor.setValueOn([InternalNode2.DIM, 0, 0], 42); + + expect(accessor.probeInternalNode1([32, 0, 0])).toBeInstanceOf(InternalNode1); + }); + + it('should hit cache L2 and return internal node 1', () => { + const accessor = new ValueAccessor3(tree); + + accessor.setValueOn([0, 0, 0], 42); + // Produce a cache miss (go over InternalNode2) + accessor.setValueOn([InternalNode1.DIM, 0, 0], 42); + + expect(accessor.probeInternalNode1([32, 0, 0])).toBeInstanceOf(InternalNode1); + }); + + it('should hit cache L1 and return internal node 1', () => { + const accessor = new ValueAccessor3(tree); + + accessor.setValueOn([0, 0, 0], 42); + + expect(accessor.probeInternalNode1([LeafNode.DIM, 0, 0])).toBeInstanceOf(InternalNode1); + }); + }); }); diff --git a/libs/vdb/src/lib/tree/value-accessor.ts b/libs/vdb/src/lib/tree/value-accessor.ts index d2d54fa0..484a1ba6 100644 --- a/libs/vdb/src/lib/tree/value-accessor.ts +++ b/libs/vdb/src/lib/tree/value-accessor.ts @@ -82,7 +82,7 @@ export class ValueAccessor3 { /** * Set the value of the voxel at the given coordinates and mark the voxel as active. */ - setValue(xyz: Coord, value: T): void { + setValueOn(xyz: Coord, value: T): void { if (this.isHashed0(xyz)) { this.leafNode.setValueAndCache(xyz, value, this); } else if (this.isHashed1(xyz)) { @@ -93,9 +93,6 @@ export class ValueAccessor3 { this.tree.root.setValueAndCache(xyz, value, this); } } - setValueOn(xyz: Coord, value: T): void { - this.setValue(xyz, value); - } /** * Set the value of the voxel at the given coordinates and mark the voxel as inactive. From e391604b517dff0a9132caf21466516d4dd8375c Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 14:14:05 +0100 Subject: [PATCH 65/67] test(vdb): check coord --- libs/vdb/src/lib/math/coord.spec.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libs/vdb/src/lib/math/coord.spec.ts diff --git a/libs/vdb/src/lib/math/coord.spec.ts b/libs/vdb/src/lib/math/coord.spec.ts new file mode 100644 index 00000000..a1b365d2 --- /dev/null +++ b/libs/vdb/src/lib/math/coord.spec.ts @@ -0,0 +1,28 @@ +import { add, areEqual, clone, Coord, createMinCoord } from './coord'; + +describe('Coord', () => { + it('should add coordinates', () => { + const c1: Coord = [1, 2, 3]; + const c2: Coord = [3, 2, 1]; + + expect(add(c1, c2)).toEqual([4, 4, 4]); + }); + + it('should create minimal coordinate', () => { + expect(createMinCoord()).toEqual([5e-324, 5e-324, 5e-324]); + }); + + it('should consider coordinates equal', () => { + const c1: Coord = [1, 2, 3]; + const c2: Coord = [1, 2, 3]; + + expect(areEqual(c1, c2)).toBeTruthy(); + }); + + it('should create clone', () => { + const c1: Coord = [1, 2, 3]; + + expect(clone(c1)).toEqual(c1); + expect(clone(c1)).not.toBe(c1); + }); +}); From a387799df0ae23d63615a3d0c3d62b840830e7e4 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 14:17:15 +0100 Subject: [PATCH 66/67] test(vdb): check grid --- libs/vdb/src/lib/grid.spec.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 libs/vdb/src/lib/grid.spec.ts diff --git a/libs/vdb/src/lib/grid.spec.ts b/libs/vdb/src/lib/grid.spec.ts new file mode 100644 index 00000000..262a0804 --- /dev/null +++ b/libs/vdb/src/lib/grid.spec.ts @@ -0,0 +1,26 @@ +import { Grid } from '@talus/vdb'; + +describe('Grid', () => { + it('should get background', () => { + const grid = new Grid(-1); + + expect(grid.background).toEqual(-1); + }); + + it('should iterate over each activated voxel', () => { + const grid = new Grid(-1); + const accessor = grid.getAccessor(); + + accessor.setValueOn([2, 1, 0], 42); + accessor.setValueOn([845, 64, 242], 42); + accessor.setValueOn([1000, 200000, 4000], 42); + + let counter = 0; + for (const voxel of grid.beginVoxelOn()) { + counter++; + expect(voxel.value).toEqual(42); + } + + expect(counter).toEqual(3); + }); +}); From 64a9c08a6acdb66f96dfd405971f29e6b742a0f4 Mon Sep 17 00:00:00 2001 From: PhilippeMorier Date: Thu, 16 Jan 2020 14:21:43 +0100 Subject: [PATCH 67/67] test(vdb): check `nodeToMesh` --- libs/vdb/src/lib/tools/node-to-mesh.spec.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts index 0b0ae6e2..00337913 100644 --- a/libs/vdb/src/lib/tools/node-to-mesh.spec.ts +++ b/libs/vdb/src/lib/tools/node-to-mesh.spec.ts @@ -26,4 +26,12 @@ describe('nodeToMesh()', () => { expect(meshData.normals.length).toEqual(meshData.positions.length); } }); + + it('should return undefined if there are no data', () => { + const grid = new Grid(0); + + const meshData = nodeToMesh(grid.tree.root, () => [0, 0, 0, 1]); + + expect(meshData).toBeUndefined(); + }); });