diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ebf24621..3fff84f5 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -56,6 +56,7 @@ import { SidenavMenuComponent } from './components/sidenav-menu/sidenav-menu.com import { SidenavComponent } from './components/sidenav/sidenav.component'; import { MediaTypePipe } from './pipes/media-type.pipe'; import { MarkdownPreviewComponent } from './components/markdown-preview/markdown-preview.component'; +import { GuideComponent } from './components/guide/guide.component'; @NgModule({ declarations: [ @@ -86,6 +87,7 @@ import { MarkdownPreviewComponent } from './components/markdown-preview/markdown EntityFeatureSettingsLightsComponent, EntityFeatureSettingsMeshComponent, MarkdownPreviewComponent, + GuideComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/guide/guide.component.html b/src/app/components/guide/guide.component.html new file mode 100644 index 00000000..0b01e53a --- /dev/null +++ b/src/app/components/guide/guide.component.html @@ -0,0 +1,7 @@ +left click +scroll +right click +

click & hold with 1 finger or left mouse button to rotate

+

scroll mouse wheel or pinch to zoom in and out

+

click & hold with 2 fingers or right mouse button to pan

+

click to dismiss

diff --git a/src/app/components/guide/guide.component.scss b/src/app/components/guide/guide.component.scss new file mode 100644 index 00000000..c5da5e1c --- /dev/null +++ b/src/app/components/guide/guide.component.scss @@ -0,0 +1,47 @@ +:host { + position: absolute; + top: 50%; + left: 50%; + translate: -50% -50%; + pointer-events: none; + + display: grid; + grid-template-columns: repeat(3, min(25vw, 25ch)); + grid-template-rows: 1fr auto; + grid-column-gap: 1rem; + grid-row-gap: 2rem; + background-color: rgba(0, 0, 0, 0.7); + border-radius: 0.75rem; + padding: 1rem; + column-gap: 1rem; + + color: white; + + align-items: center; + justify-items: center; + text-align: center; + + img { + max-height: 8rem; + max-width: 4rem; + } + + transition-property: transform, filter, backdrop-filter; + transition-duration: 500ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); + filter: opacity(0); + transform: translateY(1rem); + &.visible { + filter: opacity(1); + transform: translateY(0%); + } + + p { + margin: 0; + } + + p.dismiss { + grid-column: span 3; + font-weight: bold; + } +} diff --git a/src/app/components/guide/guide.component.spec.ts b/src/app/components/guide/guide.component.spec.ts new file mode 100644 index 00000000..2c31f780 --- /dev/null +++ b/src/app/components/guide/guide.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuideComponent } from './guide.component'; + +describe('GuideComponent', () => { + let component: GuideComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GuideComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuideComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/guide/guide.component.ts b/src/app/components/guide/guide.component.ts new file mode 100644 index 00000000..cb82c5c7 --- /dev/null +++ b/src/app/components/guide/guide.component.ts @@ -0,0 +1,33 @@ +import { AfterViewInit, Component, HostBinding } from '@angular/core'; +import { fromEvent } from 'rxjs'; +import { LoadingscreenhandlerService } from 'src/app/services/babylon/loadingscreen'; + +@Component({ + selector: 'app-guide', + templateUrl: './guide.component.html', + styleUrls: ['./guide.component.scss'], +}) +export class GuideComponent implements AfterViewInit { + @HostBinding('class.visible') + get visible() { + return this.isVisible; + } + + private isVisible = false; + + constructor(private loadingScreenHandler: LoadingscreenhandlerService) {} + + ngAfterViewInit(): void { + this.loadingScreenHandler.isLoading$.subscribe(isLoading => { + if (isLoading) return; + + setTimeout(() => { + this.isVisible = true; + }, 1_000); + }); + + fromEvent(document, 'click').subscribe(() => { + this.isVisible = false; + }); + } +} diff --git a/src/app/components/scene/scene.component.html b/src/app/components/scene/scene.component.html index 4d761d78..52934a0d 100644 --- a/src/app/components/scene/scene.component.html +++ b/src/app/components/scene/scene.component.html @@ -3,6 +3,7 @@ + diff --git a/src/app/services/babylon/loadingscreen.ts b/src/app/services/babylon/loadingscreen.ts index 0f76e7e3..ecd99f28 100644 --- a/src/app/services/babylon/loadingscreen.ts +++ b/src/app/services/babylon/loadingscreen.ts @@ -30,8 +30,8 @@ export class LoadingScreen implements ILoadingScreen { /** * Function called to display the loading screen */ - public displayLoadingUI(): void { - if (!this.loadingScreenHandler.isLoading) { + public async displayLoadingUI() { + if (!(await firstValueFrom(this.loadingScreenHandler.isLoading$))) { this.loadingScreenHandler.updateOpacity('1'); } } @@ -39,8 +39,8 @@ export class LoadingScreen implements ILoadingScreen { /** * Function called to hide the loading screen */ - public hideLoadingUI(): void { - if (this.loadingScreenHandler.isLoading) { + public async hideLoadingUI() { + if (await firstValueFrom(this.loadingScreenHandler.isLoading$)) { // setTimeout of half a second to prevent pop-in // of some bigger meshes setTimeout(() => this.loadingScreenHandler.updateOpacity('0'), 500); @@ -82,7 +82,7 @@ export class LoadingScreen implements ILoadingScreen { } import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, firstValueFrom } from 'rxjs'; @Injectable({ providedIn: 'root', @@ -92,6 +92,8 @@ export class LoadingscreenhandlerService { public opacity = this.OpacitySubject.asObservable(); private TextSubject = new BehaviorSubject('Loading'); public loadingText = this.TextSubject.asObservable(); + private isLoading = new BehaviorSubject(false); + public isLoading$ = this.isLoading.asObservable(); private StyleSubject = new BehaviorSubject({ left: '0px', @@ -102,18 +104,11 @@ export class LoadingscreenhandlerService { public loadingStyle = this.StyleSubject.asObservable(); - public isLoading = false; public backgroundColor = '#111111'; public logo = 'assets/img/kompakkt-icon.png'; - constructor() {} - public updateOpacity(newOpacity: string): void { - if (parseFloat(newOpacity) > 0.5) { - this.isLoading = true; - } else { - this.isLoading = false; - } + this.isLoading.next(parseFloat(newOpacity) > 0.5); this.OpacitySubject.next(newOpacity); } diff --git a/src/app/services/processing/processing.service.ts b/src/app/services/processing/processing.service.ts index 27f2bb42..1680dd14 100644 --- a/src/app/services/processing/processing.service.ts +++ b/src/app/services/processing/processing.service.ts @@ -488,7 +488,8 @@ export class ProcessingService { public async loadEntity(newEntity: IEntity, overrideUrl?: string) { const baseURL = overrideUrl ?? this.baseUrl; - if (!this.loadingScreenHandler.isLoading && newEntity.processed && newEntity.mediaType) { + const isLoading = await firstValueFrom(this.loadingScreenHandler.isLoading$); + if (!isLoading && newEntity.processed && newEntity.mediaType) { if (!newEntity.dataSource.isExternal) { this.entityMediaType = newEntity.mediaType; await this.initialiseEntitySettingsData(newEntity); diff --git a/src/assets/icons/guide/left_click_move.svg b/src/assets/icons/guide/left_click_move.svg new file mode 100644 index 00000000..e6aef845 --- /dev/null +++ b/src/assets/icons/guide/left_click_move.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/guide/right_click_move.svg b/src/assets/icons/guide/right_click_move.svg new file mode 100644 index 00000000..8fe5ef61 --- /dev/null +++ b/src/assets/icons/guide/right_click_move.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icons/guide/scroll_wheel.svg b/src/assets/icons/guide/scroll_wheel.svg new file mode 100644 index 00000000..a575378c --- /dev/null +++ b/src/assets/icons/guide/scroll_wheel.svg @@ -0,0 +1,6 @@ + + + + + +