UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

194 lines (165 loc) 5.01 kB
import {SVGLoader, SVGResult, StrokeStyle} from 'three/examples/jsm/loaders/SVGLoader'; import { ShapeGeometry, LineSegments, ShapePath, Mesh, DoubleSide, LineBasicMaterial, MeshBasicMaterial, Group, Color, } from 'three'; import {isBooleanTrue} from '../BooleanValue'; import {CoreBaseLoader} from './_Base'; import {BaseNodeType} from '../../engine/nodes/_Base'; import {Poly} from '../../engine/Poly'; interface CoreSVGLoaderOptions { // fill drawFillShapes: boolean; fillShapesWireframe: boolean; // strokes drawStrokes: boolean; strokesWireframe: boolean; // style override tStyleOverride: boolean; strokeWidth: number; // advanced tadvanced: boolean; isCCW: boolean; // noHoles: boolean; } interface StrokeStyleExtended extends StrokeStyle { fill: string; fillOpacity: number; stroke: string; strokeOpacity: number; } interface SVGPathUserData { style: StrokeStyleExtended; } export class CoreSVGLoader extends CoreBaseLoader<string> { constructor(url: string, _node?: BaseNodeType) { super(url, _node); } load(options: CoreSVGLoaderOptions): Promise<Group> { if (this._node) { Poly.blobs.clearBlobsForNode(this._node); } return new Promise(async (resolve, reject) => { const loader = new SVGLoader(this.loadingManager); // let resolvedUrl = this.url; //.includes('?') ? this.url : `${this.url}?${Date.now()}`; // const paramUrl = this.url; // const blobUrl = Poly.blobs.blobUrl(resolvedUrl); // if (blobUrl) { // resolvedUrl = blobUrl; // } else { // if (resolvedUrl[0] != 'h') { // const assets_root = this.scene.assets.root(); // if (assets_root) { // resolvedUrl = `${assets_root}${resolvedUrl}`; // } // } // } const url = this._urlToLoad(); loader.load( url, (data) => { try { const group = this._onLoaded(data, options); resolve(group); } catch (err) { reject(err); } }, undefined, (err) => { reject(err); } ); }); } parse(text: string, options: CoreSVGLoaderOptions) { const loader = new SVGLoader(this.loadingManager); const data = loader.parse(text); const group = this._onLoaded(data, options); return group; } private _onLoaded(data: SVGResult, options: CoreSVGLoaderOptions) { const paths = data.paths; const group = new Group(); for (let i = 0; i < paths.length; i++) { const path = paths[i]; const userData: SVGPathUserData = (path as any).userData; const fillColor = userData.style.fill; if (isBooleanTrue(options.drawFillShapes) && fillColor !== undefined && fillColor !== 'none') { this._drawShapes(group, path, options); } // const strokeColor = userData.style.stroke; if (isBooleanTrue(options.drawStrokes)) { this._drawStrokes(group, path, options); } } return group; } private _drawShapes(group: Group, path: ShapePath, options: CoreSVGLoaderOptions) { const userData: SVGPathUserData = (path as any).userData; const material = new MeshBasicMaterial({ color: new Color().setStyle(userData.style.fill), opacity: userData.style.fillOpacity, transparent: userData.style.fillOpacity < 1, side: DoubleSide, depthWrite: false, wireframe: options.fillShapesWireframe, }); const isCCW = options.tadvanced && options.isCCW; // const noHoles = options.tadvanced && options.noHoles; const shapes = path.toShapes(isCCW); for (let j = 0; j < shapes.length; j++) { const shape = shapes[j]; const geometry = new ShapeGeometry(shape); const mesh = new Mesh(geometry, material); group.add(mesh); } } private _drawStrokes(group: Group, path: ShapePath, options: CoreSVGLoaderOptions) { const userData: SVGPathUserData = (path as any).userData; if (options.tStyleOverride) { userData.style.strokeWidth = options.strokeWidth; } if (options.strokesWireframe) { const material = new LineBasicMaterial({ color: new Color().setStyle(userData.style.stroke), opacity: userData.style.strokeOpacity, transparent: userData.style.strokeOpacity < 1, side: DoubleSide, depthWrite: false, }); for (let j = 0, jl = path.subPaths.length; j < jl; j++) { const subPath = path.subPaths[j]; const geometry = SVGLoader.pointsToStroke(subPath.getPoints(), userData.style); if (geometry) { const mesh = new LineSegments(geometry, material); group.add(mesh); } } } else { const material = new MeshBasicMaterial({ color: new Color().setStyle(userData.style.stroke), opacity: userData.style.strokeOpacity, transparent: userData.style.strokeOpacity < 1, side: DoubleSide, depthWrite: false, // wireframe: options.strokesWireframe, }); for (let j = 0, jl = path.subPaths.length; j < jl; j++) { const subPath = path.subPaths[j]; const geometry = SVGLoader.pointsToStroke(subPath.getPoints(), userData.style); if (geometry) { const mesh = new Mesh(geometry, material); group.add(mesh); } } } } }