From 68d9ade2941cf71f9ec5e4ed155172f5554dd43a Mon Sep 17 00:00:00 2001 From: Ben Halverson Date: Sat, 28 Dec 2024 13:33:30 -0800 Subject: [PATCH 1/3] wip --- package-lock.json | 109 ++++++++++++++++++ package.json | 3 + .../product-details.component.css | 6 + .../product-details.component.html | 2 + .../product-details.component.ts | 30 ++++- tsconfig.json | 1 + 6 files changed, 150 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2422b18..a1ab838 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,11 @@ "@angular/platform-server": "^19.0.1", "@angular/router": "^19.0.1", "@angular/ssr": "^19.0.2", + "@windmillcode/wml-components-base": "^19.0.5000", + "@windmillcode/wml-three": "^19.0.5000", "ngx-toastr": "^19.0.0", "rxjs": "~7.8.0", + "three": "^0.170.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, @@ -6379,6 +6382,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "license": "MIT", + "peer": true + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -6628,6 +6638,35 @@ "@types/node": "*" } }, + "node_modules/@types/stats.js": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", + "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/three": { + "version": "0.170.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.170.0.tgz", + "integrity": "sha512-CUm2uckq+zkCY7ZbFpviRttY+6f9fvwm6YqSqPfA5K22s9w7R4VnA3rzJse8kHVvuzLcTx+CjNCs2NYe0QFAyg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz", + "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==", + "license": "MIT", + "peer": true + }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -6812,6 +6851,42 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@webgpu/types": { + "version": "0.1.52", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.52.tgz", + "integrity": "sha512-eI883Nlag2hGIkhXxAnq8s4APpqXWuPL3Gbn2ghiU12UjLvfCbVqHK4XfXl3eLRTatqcMmeK7jws7IwWsGfbzw==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@windmillcode/wml-components-base": { + "version": "19.0.5000", + "resolved": "https://registry.npmjs.org/@windmillcode/wml-components-base/-/wml-components-base-19.0.5000.tgz", + "integrity": "sha512-Plm4eNKafZnqQZHjn6Z0mtkS/h17/wpK4F0RBp91UtwEIx86OkIP+5SdEsRxCLfXkL23cuzVNu32rnlN3baS1w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/WindMillCode" + } + }, + "node_modules/@windmillcode/wml-three": { + "version": "19.0.5000", + "resolved": "https://registry.npmjs.org/@windmillcode/wml-three/-/wml-three-19.0.5000.tgz", + "integrity": "sha512-gf379stfRznBB+zq66Qkaxo0HcsoFOAJJqzllW9Lz3lcgRi3UNBXGckker1838f3jgqYuDZjwDTUJ+UoS3y6Kw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/WindMillCode" + }, + "peerDependencies": { + "@types/three": "^0.170.0", + "@windmillcode/wml-components-base": "^19.0.5000", + "dat.gui": "^0.7.9", + "lil-gui": "^0.19.2", + "three": "^0.170.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -8460,6 +8535,13 @@ "dev": true, "license": "MIT" }, + "node_modules/dat.gui": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz", + "integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==", + "license": "Apache-2.0", + "peer": true + }, "node_modules/data-uri-to-buffer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", @@ -9330,6 +9412,13 @@ "node": ">=0.8.0" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT", + "peer": true + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -11199,6 +11288,13 @@ } } }, + "node_modules/lil-gui": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.19.2.tgz", + "integrity": "sha512-nU8j4ND702ouGfQZoaTN4dfXxacvGOAVK0DtmZBVcUYUAeYQXLQAjAN50igMHiba3T5jZyKEjXZU+Ntm1Qs6ZQ==", + "license": "MIT", + "peer": true + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -11844,6 +11940,13 @@ "node": ">= 8" } }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", + "license": "MIT", + "peer": true + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -15897,6 +16000,12 @@ "tslib": "^2" } }, + "node_modules/three": { + "version": "0.170.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz", + "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==", + "license": "MIT" + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", diff --git a/package.json b/package.json index 47ff692..31e29ea 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,11 @@ "@angular/platform-server": "^19.0.1", "@angular/router": "^19.0.1", "@angular/ssr": "^19.0.2", + "@windmillcode/wml-components-base": "^19.0.5000", + "@windmillcode/wml-three": "^19.0.5000", "ngx-toastr": "^19.0.0", "rxjs": "~7.8.0", + "three": "^0.170.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, diff --git a/src/app/product-details/product-details.component.css b/src/app/product-details/product-details.component.css index e69de29..ed6f97b 100644 --- a/src/app/product-details/product-details.component.css +++ b/src/app/product-details/product-details.component.css @@ -0,0 +1,6 @@ + +.renderer { + width: 25vw; + height:25vh; + background-color: green; + } diff --git a/src/app/product-details/product-details.component.html b/src/app/product-details/product-details.component.html index 505605d..bc67f03 100644 --- a/src/app/product-details/product-details.component.html +++ b/src/app/product-details/product-details.component.html @@ -91,4 +91,6 @@

Product Details

} + +
diff --git a/src/app/product-details/product-details.component.ts b/src/app/product-details/product-details.component.ts index e293f5a..9285498 100644 --- a/src/app/product-details/product-details.component.ts +++ b/src/app/product-details/product-details.component.ts @@ -1,9 +1,14 @@ -import { Component } from '@angular/core'; +import { Component, ViewChild, ViewContainerRef } from '@angular/core'; import { Product, ProductService } from '../product.service'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { catchError, of, Subject, switchMap, takeUntil, tap } from 'rxjs'; import { FormBuilder, FormGroup, FormsModule, NgModel, ReactiveFormsModule, Validators } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; +import { + WMLThreeCommonObjectProps, + WMLThreeCommonProps, +} from '@windmillcode/wml-three'; +import { BoxGeometry, Vector3, MeshBasicMaterial } from 'three'; @Component({ selector: 'app-product-details', @@ -20,6 +25,11 @@ export class ProductDetailsComponent { private destroy$ = new Subject(); + @ViewChild('renderer', { read: ViewContainerRef, static: true }) + renderer!: ViewContainerRef; + ngUnsub = new Subject(); + three!: WMLThreeCommonProps; + constructor( private readonly productService: ProductService, private readonly route: ActivatedRoute, @@ -35,6 +45,24 @@ export class ProductDetailsComponent { } ngOnInit() { + + let box = new WMLThreeCommonObjectProps({ + geometry: new BoxGeometry(7, 7, 7), + material: new MeshBasicMaterial({ + color: 0x11ff00, + }), + }); + this.three = new WMLThreeCommonProps({ + rendererParentElement: this.renderer.element.nativeElement, + objects: [box], + }); + + this.three.init({}); + this.three.updateCameraPosition({ + position: new Vector3(-60, 20, -20), + updateControls: true, + }); + this.route.params .pipe( switchMap((params: Params) => diff --git a/tsconfig.json b/tsconfig.json index 8d623e2..fb66ed8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "./dist/out-tsc", "strict": true, "noImplicitOverride": true, + "noImplicitAny": false, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, From 43e805172a6edb333067b69facc7d1911bd30197 Mon Sep 17 00:00:00 2001 From: Ben Halverson Date: Tue, 7 Jan 2025 20:32:57 -0800 Subject: [PATCH 2/3] it works sorta --- package-lock.json | 737 +----------------- package.json | 4 +- .../product-details.component.css | 2 +- .../product-details.component.ts | 200 ++++- 4 files changed, 185 insertions(+), 758 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1ab838..53dd118 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,8 @@ "@angular/platform-server": "^19.0.1", "@angular/router": "^19.0.1", "@angular/ssr": "^19.0.2", - "@windmillcode/wml-components-base": "^19.0.5000", - "@windmillcode/wml-three": "^19.0.5000", + "@windmillcode/wml-components-base": "^19.0.5100", + "@windmillcode/wml-three": "^19.0.5100", "ngx-toastr": "^19.0.0", "rxjs": "~7.8.0", "three": "^0.170.0", @@ -116,40 +116,6 @@ } } }, - "node_modules/@angular-devkit/architect/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-devkit/architect/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/build-angular": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.0.2.tgz", @@ -712,24 +678,6 @@ "node": ">=18" } }, - "node_modules/@angular-devkit/build-angular/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/esbuild": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", @@ -771,22 +719,6 @@ "@esbuild/win32-x64": "0.24.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1900.2", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1900.2.tgz", @@ -854,40 +786,6 @@ } } }, - "node_modules/@angular-devkit/schematics/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular/animations": { "version": "19.0.1", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.1.tgz", @@ -1490,40 +1388,6 @@ } } }, - "node_modules/@angular/cli/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/cli/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular/common": { "version": "19.0.1", "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.1.tgz", @@ -3600,438 +3464,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@fastify/busboy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", @@ -6046,40 +5478,6 @@ } } }, - "node_modules/@schematics/angular/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@schematics/angular/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@sigstore/bundle": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.0.0.tgz", @@ -6382,13 +5780,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@tweenjs/tween.js": { - "version": "23.1.3", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", - "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", - "license": "MIT", - "peer": true - }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -6638,35 +6029,6 @@ "@types/node": "*" } }, - "node_modules/@types/stats.js": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", - "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/three": { - "version": "0.170.0", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.170.0.tgz", - "integrity": "sha512-CUm2uckq+zkCY7ZbFpviRttY+6f9fvwm6YqSqPfA5K22s9w7R4VnA3rzJse8kHVvuzLcTx+CjNCs2NYe0QFAyg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@tweenjs/tween.js": "~23.1.3", - "@types/stats.js": "*", - "@types/webxr": "*", - "@webgpu/types": "*", - "fflate": "~0.8.2", - "meshoptimizer": "~0.18.1" - } - }, - "node_modules/@types/webxr": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz", - "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==", - "license": "MIT", - "peer": true - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -6851,17 +6213,10 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webgpu/types": { - "version": "0.1.52", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.52.tgz", - "integrity": "sha512-eI883Nlag2hGIkhXxAnq8s4APpqXWuPL3Gbn2ghiU12UjLvfCbVqHK4XfXl3eLRTatqcMmeK7jws7IwWsGfbzw==", - "license": "BSD-3-Clause", - "peer": true - }, "node_modules/@windmillcode/wml-components-base": { - "version": "19.0.5000", - "resolved": "https://registry.npmjs.org/@windmillcode/wml-components-base/-/wml-components-base-19.0.5000.tgz", - "integrity": "sha512-Plm4eNKafZnqQZHjn6Z0mtkS/h17/wpK4F0RBp91UtwEIx86OkIP+5SdEsRxCLfXkL23cuzVNu32rnlN3baS1w==", + "version": "19.0.5100", + "resolved": "https://registry.npmjs.org/@windmillcode/wml-components-base/-/wml-components-base-19.0.5100.tgz", + "integrity": "sha512-YNHcCqo5nGPzIOGBQbB1VmI0BzI49zL3OdKpGNLHAxtjA7SvaxTZ3zH0HafMg9FeY0xa2fpyrlYRC/fZN0E2YA==", "dependencies": { "tslib": "^2.3.0" }, @@ -6870,9 +6225,9 @@ } }, "node_modules/@windmillcode/wml-three": { - "version": "19.0.5000", - "resolved": "https://registry.npmjs.org/@windmillcode/wml-three/-/wml-three-19.0.5000.tgz", - "integrity": "sha512-gf379stfRznBB+zq66Qkaxo0HcsoFOAJJqzllW9Lz3lcgRi3UNBXGckker1838f3jgqYuDZjwDTUJ+UoS3y6Kw==", + "version": "19.0.5100", + "resolved": "https://registry.npmjs.org/@windmillcode/wml-three/-/wml-three-19.0.5100.tgz", + "integrity": "sha512-pMQI7vcR3Qjv/mMT1UoISRWKafd7eHJXKds4PrrLmqr90KulDCg7UmS0AkBYhYcIaYR7nIFccXjtEeOYT4WYOg==", "dependencies": { "tslib": "^2.3.0" }, @@ -6881,10 +6236,9 @@ }, "peerDependencies": { "@types/three": "^0.170.0", - "@windmillcode/wml-components-base": "^19.0.5000", - "dat.gui": "^0.7.9", - "lil-gui": "^0.19.2", - "three": "^0.170.0" + "@windmillcode/wml-components-base": "^19.0.5100", + "lil-gui": "0.20.0", + "three": "0.171.0" } }, "node_modules/@xtuc/ieee754": { @@ -8535,13 +7889,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dat.gui": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz", - "integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==", - "license": "Apache-2.0", - "peer": true - }, "node_modules/data-uri-to-buffer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", @@ -9077,47 +8424,6 @@ "dev": true, "license": "MIT" }, - "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" - } - }, "node_modules/esbuild-wasm": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.0.tgz", @@ -9412,13 +8718,6 @@ "node": ">=0.8.0" } }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT", - "peer": true - }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -11288,13 +10587,6 @@ } } }, - "node_modules/lil-gui": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.19.2.tgz", - "integrity": "sha512-nU8j4ND702ouGfQZoaTN4dfXxacvGOAVK0DtmZBVcUYUAeYQXLQAjAN50igMHiba3T5jZyKEjXZU+Ntm1Qs6ZQ==", - "license": "MIT", - "peer": true - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -11940,13 +11232,6 @@ "node": ">= 8" } }, - "node_modules/meshoptimizer": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", - "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", - "license": "MIT", - "peer": true - }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", diff --git a/package.json b/package.json index 31e29ea..2aef14b 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "@angular/platform-server": "^19.0.1", "@angular/router": "^19.0.1", "@angular/ssr": "^19.0.2", - "@windmillcode/wml-components-base": "^19.0.5000", - "@windmillcode/wml-three": "^19.0.5000", + "@windmillcode/wml-components-base": "^19.0.5100", + "@windmillcode/wml-three": "^19.0.5100", "ngx-toastr": "^19.0.0", "rxjs": "~7.8.0", "three": "^0.170.0", diff --git a/src/app/product-details/product-details.component.css b/src/app/product-details/product-details.component.css index ed6f97b..daf8113 100644 --- a/src/app/product-details/product-details.component.css +++ b/src/app/product-details/product-details.component.css @@ -2,5 +2,5 @@ .renderer { width: 25vw; height:25vh; - background-color: green; + background-color: red; } diff --git a/src/app/product-details/product-details.component.ts b/src/app/product-details/product-details.component.ts index 9285498..804d0f5 100644 --- a/src/app/product-details/product-details.component.ts +++ b/src/app/product-details/product-details.component.ts @@ -1,14 +1,36 @@ -import { Component, ViewChild, ViewContainerRef } from '@angular/core'; -import { Product, ProductService } from '../product.service'; +import { Component, Inject, PLATFORM_ID, ViewChild, ViewContainerRef } from '@angular/core'; +import { ProductResponse, ProductService } from '../product.service'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { catchError, of, Subject, switchMap, takeUntil, tap } from 'rxjs'; -import { FormBuilder, FormGroup, FormsModule, NgModel, ReactiveFormsModule, Validators } from '@angular/forms'; +import { catchError, of, Subject, switchMap, takeUntil, tap, timer } from 'rxjs'; +import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; import { WMLThreeCommonObjectProps, WMLThreeCommonProps, + WMLThreeLightProps, + WMLThreeTexturesProps, } from '@windmillcode/wml-three'; -import { BoxGeometry, Vector3, MeshBasicMaterial } from 'three'; +import { + BoxGeometry, + Vector3, + Color, + AmbientLight, + MeshStandardMaterial, + TextureLoader, + SphereGeometry, + EquirectangularReflectionMapping, + MeshPhysicalMaterial, + Mesh, + MeshPhongMaterial, +} from 'three'; +import { generateRandomColor } from '@windmillcode/wml-components-base'; +import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'; +import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'; +import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; + + + @Component({ selector: 'app-product-details', @@ -18,50 +40,170 @@ import { BoxGeometry, Vector3, MeshBasicMaterial } from 'three'; }) export class ProductDetailsComponent { - productForm: FormGroup - productDetails = {} as Product; - editableDetails = {} as Product; + productForm: FormGroup; + productDetails = {} as ProductResponse; + editableDetails = {} as ProductResponse; isEditing = false; private destroy$ = new Subject(); - @ViewChild('renderer', { read: ViewContainerRef, static: true }) renderer!: ViewContainerRef; ngUnsub = new Subject(); three!: WMLThreeCommonProps; + threeOne!: WMLThreeCommonProps; + threeTwo!: WMLThreeCommonProps; + threeThree!: WMLThreeCommonProps; + threeFour!: WMLThreeCommonProps; constructor( private readonly productService: ProductService, private readonly route: ActivatedRoute, private readonly router: Router, private readonly fb: FormBuilder, - private readonly toastr: ToastrService + private readonly toastr: ToastrService, ) { this.productForm = this.fb.group({ name: [''], - description: ['', ], + description: ['',], filamentType: [''], }); } - ngOnInit() { - - let box = new WMLThreeCommonObjectProps({ - geometry: new BoxGeometry(7, 7, 7), - material: new MeshBasicMaterial({ - color: 0x11ff00, - }), - }); - this.three = new WMLThreeCommonProps({ - rendererParentElement: this.renderer.element.nativeElement, - objects: [box], - }); - - this.three.init({}); - this.three.updateCameraPosition({ + createRenderer(three: WMLThreeCommonProps) { + three.init(); + three.updateCameraPosition({ position: new Vector3(-60, 20, -20), updateControls: true, }); + } + + ngOnInit() { + + timer(2000) + .pipe( + tap(() => { + [ + this.renderer, + // this.rendererTwo, + // this.rendererThree, + // this.rendererFour, + // this.rendererFive, + ].forEach((renderer, index0) => { + let model = new WMLThreeCommonObjectProps({ + geometry: new BoxGeometry(12, 12, 12), + material: new MeshStandardMaterial({ + color: new Color(generateRandomColor()), + }), + }); + let sphere = new WMLThreeCommonObjectProps({ + geometry: new SphereGeometry(12, 30, 30), + material: new MeshPhysicalMaterial({ + roughness: 0.5, + metalness: 0.7, + color: 0xaa0000, + transmission: 0.5, // Makes the material fully transparent, allowing light to pass through like glass. + ior: 2.33, // Index of refraction + }), + }); + + if (index0 === 0) { + model = new WMLThreeCommonObjectProps({ + texture: new WMLThreeTexturesProps({ + group: [ + { + url: 'https://pub-0ec69c7d5c064de8b57f5d594f07bc02.r2.dev/6_hole_gear_v5_upload.stl', + loader: new STLLoader(), + onLoad: (geometry) => { + try { + const scene = three.getCurentScene(); + // Default material + let material = new MeshPhongMaterial({ + color: 0xaa3333, + }); + + // Handle geometries with vertex colors + if (geometry.hasColors) { + material = new MeshPhongMaterial({ + opacity: geometry.alpha || 1, + vertexColors: true, + transparent: geometry.alpha < 1, // Enable transparency if alpha is less than 1 + }); + } + + // Handle multiple solids in ASCII STLs + let mesh; + if (geometry.groups?.length > 0) { + const materials = geometry.groups.map( + (group, index) => { + return new MeshPhongMaterial({ + color: new Color( + `hsl(${ + (index / geometry.groups.length) * 360 + }, 100%, 50%)` + ), + wireframe: false, + }); + } + ); + + mesh = new Mesh(geometry, materials); + } else { + // Single solid or binary STL + mesh = new Mesh(geometry, material); + } + + // Optional scaling for large or small geometries + if (geometry.boundingBox) { + const size = new Vector3(); + geometry.boundingBox.getSize(size); + if (size.length() > 100) { + console.warn('Geometry is large, scaling down.'); + mesh.scale.set(0.1, 0.1, 0.1); + } else if (size.length() < 1) { + console.warn('Geometry is small, scaling up.'); + mesh.scale.set(10, 10, 10); + } + } else { + console.warn( + 'No bounding box detected; scaling skipped.' + ); + } + + // Add mesh to the scene + scene.add(mesh); + } catch (error) { + console.error('Error handling STL geometry:', error); + } + }, + + onError: (err) => { + console.log(err); + }, + }, + ], + }), + }); + } + let three = new WMLThreeCommonProps({ + rendererParentElement: renderer.element.nativeElement, + objects: [model], + lights: [ + new WMLThreeLightProps({ + light: new AmbientLight(0xffffff, 10), + }), + ], + }); + if (index0 === 3) { + three.objects.push(sphere); + } + + this.createRenderer(three); + }); + }) + ) + .subscribe(); + + this.route.params .pipe( @@ -78,14 +220,14 @@ export class ProductDetailsComponent { } saveChanges() { - if(this.productForm.invalid) { + if (this.productForm.invalid) { return; } - const updatedProduct: Product = { + const updatedProduct: ProductResponse = { ...this.productDetails, ...this.productForm.value, - } + }; this.productService .updateProduct(updatedProduct) From 854cb42288ac98bc45a1d058c87391aa588b359c Mon Sep 17 00:00:00 2001 From: Ben Halverson Date: Fri, 31 Jan 2025 19:29:28 -0800 Subject: [PATCH 3/3] it works --- .../product-details.component.html | 113 +++---- .../product-details.component.ts | 309 ++++++------------ 2 files changed, 147 insertions(+), 275 deletions(-) diff --git a/src/app/product-details/product-details.component.html b/src/app/product-details/product-details.component.html index bc67f03..1075caa 100644 --- a/src/app/product-details/product-details.component.html +++ b/src/app/product-details/product-details.component.html @@ -9,8 +9,7 @@

Product Details

- @if(!isEditing) { -
+

Name: {{ productDetails.name }}

@@ -19,78 +18,56 @@

Product Details

{{ productDetails.description }}

- FilamentType: + Filament Type: {{ productDetails.filamentType }}

- } @if(isEditing) { -
-
- - - -
- - -
+ + + + +
+ +
- } -
diff --git a/src/app/product-details/product-details.component.ts b/src/app/product-details/product-details.component.ts index 804d0f5..3078fb7 100644 --- a/src/app/product-details/product-details.component.ts +++ b/src/app/product-details/product-details.component.ts @@ -1,254 +1,149 @@ -import { Component, Inject, PLATFORM_ID, ViewChild, ViewContainerRef } from '@angular/core'; -import { ProductResponse, ProductService } from '../product.service'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { catchError, of, Subject, switchMap, takeUntil, tap, timer } from 'rxjs'; -import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, ViewChild, ViewContainerRef } from '@angular/core'; +import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; import { - WMLThreeCommonObjectProps, WMLThreeCommonProps, WMLThreeLightProps, - WMLThreeTexturesProps, } from '@windmillcode/wml-three'; -import { - BoxGeometry, - Vector3, - Color, - AmbientLight, - MeshStandardMaterial, - TextureLoader, - SphereGeometry, - EquirectangularReflectionMapping, - MeshPhysicalMaterial, - Mesh, - MeshPhongMaterial, -} from 'three'; -import { generateRandomColor } from '@windmillcode/wml-components-base'; -import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'; -import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'; import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; - - - +import { AmbientLight, Color, Mesh, MeshPhongMaterial, Vector3 } from 'three'; +import { Subject, of } from 'rxjs'; +import { tap, takeUntil, catchError } from 'rxjs'; +import { NgIf } from '@angular/common'; @Component({ selector: 'app-product-details', - imports: [ReactiveFormsModule], + imports: [ReactiveFormsModule, NgIf], templateUrl: './product-details.component.html', styleUrl: './product-details.component.css', }) export class ProductDetailsComponent { - productForm: FormGroup; - productDetails = {} as ProductResponse; - editableDetails = {} as ProductResponse; + productDetails = { + name: 'Sample Product', + description: 'This is a sample product.', + filamentType: 'PLA', + stl: 'https://pub-0ec69c7d5c064de8b57f5d594f07bc02.r2.dev/6_hole_gear_v5_upload.stl', // Default STL file + }; isEditing = false; private destroy$ = new Subject(); @ViewChild('renderer', { read: ViewContainerRef, static: true }) renderer!: ViewContainerRef; - ngUnsub = new Subject(); - three!: WMLThreeCommonProps; - threeOne!: WMLThreeCommonProps; - threeTwo!: WMLThreeCommonProps; - threeThree!: WMLThreeCommonProps; - threeFour!: WMLThreeCommonProps; + private three!: WMLThreeCommonProps; constructor( - private readonly productService: ProductService, - private readonly route: ActivatedRoute, - private readonly router: Router, private readonly fb: FormBuilder, - private readonly toastr: ToastrService, + private readonly toastr: ToastrService ) { this.productForm = this.fb.group({ - name: [''], - description: ['',], - filamentType: [''], - }); - } - - createRenderer(three: WMLThreeCommonProps) { - three.init(); - three.updateCameraPosition({ - position: new Vector3(-60, 20, -20), - updateControls: true, + name: [ + this.productDetails.name, + [Validators.required, Validators.maxLength(100)], + ], + description: [this.productDetails.description, Validators.required], + filamentType: [this.productDetails.filamentType], + stl: [this.productDetails.stl, Validators.required], }); } - ngOnInit() { - - timer(2000) - .pipe( - tap(() => { - [ - this.renderer, - // this.rendererTwo, - // this.rendererThree, - // this.rendererFour, - // this.rendererFive, - ].forEach((renderer, index0) => { - let model = new WMLThreeCommonObjectProps({ - geometry: new BoxGeometry(12, 12, 12), - material: new MeshStandardMaterial({ - color: new Color(generateRandomColor()), - }), - }); - let sphere = new WMLThreeCommonObjectProps({ - geometry: new SphereGeometry(12, 30, 30), - material: new MeshPhysicalMaterial({ - roughness: 0.5, - metalness: 0.7, - color: 0xaa0000, - transmission: 0.5, // Makes the material fully transparent, allowing light to pass through like glass. - ior: 2.33, // Index of refraction - }), - }); - - if (index0 === 0) { - model = new WMLThreeCommonObjectProps({ - texture: new WMLThreeTexturesProps({ - group: [ - { - url: 'https://pub-0ec69c7d5c064de8b57f5d594f07bc02.r2.dev/6_hole_gear_v5_upload.stl', - loader: new STLLoader(), - onLoad: (geometry) => { - try { - const scene = three.getCurentScene(); - // Default material - let material = new MeshPhongMaterial({ - color: 0xaa3333, - }); - - // Handle geometries with vertex colors - if (geometry.hasColors) { - material = new MeshPhongMaterial({ - opacity: geometry.alpha || 1, - vertexColors: true, - transparent: geometry.alpha < 1, // Enable transparency if alpha is less than 1 - }); - } - - // Handle multiple solids in ASCII STLs - let mesh; - if (geometry.groups?.length > 0) { - const materials = geometry.groups.map( - (group, index) => { - return new MeshPhongMaterial({ - color: new Color( - `hsl(${ - (index / geometry.groups.length) * 360 - }, 100%, 50%)` - ), - wireframe: false, - }); - } - ); - - mesh = new Mesh(geometry, materials); - } else { - // Single solid or binary STL - mesh = new Mesh(geometry, material); - } - - // Optional scaling for large or small geometries - if (geometry.boundingBox) { - const size = new Vector3(); - geometry.boundingBox.getSize(size); - if (size.length() > 100) { - console.warn('Geometry is large, scaling down.'); - mesh.scale.set(0.1, 0.1, 0.1); - } else if (size.length() < 1) { - console.warn('Geometry is small, scaling up.'); - mesh.scale.set(10, 10, 10); - } - } else { - console.warn( - 'No bounding box detected; scaling skipped.' - ); - } - - // Add mesh to the scene - scene.add(mesh); - } catch (error) { - console.error('Error handling STL geometry:', error); - } - }, - - onError: (err) => { - console.log(err); - }, - }, - ], - }), - }); - } - let three = new WMLThreeCommonProps({ - rendererParentElement: renderer.element.nativeElement, - objects: [model], - lights: [ - new WMLThreeLightProps({ - light: new AmbientLight(0xffffff, 10), - }), - ], - }); - if (index0 === 3) { - three.objects.push(sphere); - } - - this.createRenderer(three); - }); - }) - ) - .subscribe(); - + ngOnInit(): void { + this.initializeRenderer(); + // Load the initial STL file + this.loadSTLModel(this.productDetails.stl); - this.route.params + // Watch for changes in the STL URL field and reload the viewer + this.productForm.get('stl')?.valueChanges .pipe( - switchMap((params: Params) => - this.productService.getProductById(params['id']) - ), - tap((product) => { - this.productDetails = product; - this.productForm.patchValue(product); + tap((url) => { + this.loadSTLModel(url); }), takeUntil(this.destroy$) ) .subscribe(); } - saveChanges() { + saveChanges(): void { if (this.productForm.invalid) { + this.toastr.warning('Please fix the errors in the form.'); return; } - const updatedProduct: ProductResponse = { - ...this.productDetails, - ...this.productForm.value, - }; + // Update the product details and toggle editing mode + this.productDetails = { ...this.productForm.value }; + this.isEditing = false; + this.toastr.success('Product details updated successfully!'); + } - this.productService - .updateProduct(updatedProduct) - .pipe( - tap(() => { - this.productDetails = updatedProduct; - this.isEditing = false; - this.toastr.success('Product updated successfully'); - this.router.navigate(['/products']); - }), - catchError((error) => { - this.toastr.error('Error updating product'); - // this.router.navigate(['/']); - return of(error); + private initializeRenderer(): void { + // Initialize the Three.js renderer using the WMLThreeCommonProps + this.three = new WMLThreeCommonProps({ + rendererParentElement: this.renderer.element.nativeElement, + objects: [], + lights: [ + new WMLThreeLightProps({ + light: new AmbientLight(0xffffff, 10), }), - takeUntil(this.destroy$) - ) - .subscribe(); + ], + }); + + this.three.init(); + this.three.updateCameraPosition({ + position: new Vector3(-60, 20, -20), + updateControls: true, + }); + } + + private loadSTLModel(url: string): void { + if (!url) { + this.toastr.warning('Please provide a valid STL URL.'); + return; + } + + const loader = new STLLoader(); + loader.load( + url, + (geometry) => { + try { + const material = new MeshPhongMaterial({ + color: new Color(0xaa3333), + }); + const mesh = new Mesh(geometry, material); + + // Scale the geometry if necessary + if (geometry.boundingBox) { + const size = new Vector3(); + geometry.boundingBox.getSize(size); + const maxSize = Math.max(size.x, size.y, size.z); + if (maxSize > 100) { + mesh.scale.set(0.1, 0.1, 0.1); // Scale down large models + } else if (maxSize < 1) { + mesh.scale.set(10, 10, 10); // Scale up small models + } + } + + // Clear the current scene and add the new mesh + const scene = this.three.getCurentScene(); + scene.clear(); + scene.add(mesh); + + // Render the updated scene + this.three.renderer(); + } catch (error) { + this.toastr.error('Failed to load the STL model.'); + console.error('Error rendering STL model:', error); + } + }, + undefined, + (error) => { + this.toastr.error('Error loading STL file.'); + console.error('Error loading STL file:', error); + } + ); } - ngOnDestroy() { + ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); }