| @@ -5,6 +5,7 @@ module.exports = { | |||
| ], | |||
| 'parserOptions': { | |||
| 'ecmaVersion': 2018, | |||
| 'sourceType': 'module', // Allows for the use of imports | |||
| }, | |||
| 'plugins': [ | |||
| 'html', | |||
| @@ -13,7 +13,7 @@ A new way to work with three.js, 3D models and rendering on the web. | |||
| [](https://opensource.org/license/apache-2-0/) | |||
| [](https://twitter.com/repalash) | |||
| ThreePipe is a 3D framework built on top of [three.js](https://threejs.org/) in TypeScript with a focus on quality rendering, modularity and extensibility. | |||
| ThreePipe is a 3D framework built on top of [three.js](https://threejs.org/) in TypeScript with a focus on rendering quality, modularity and extensibility. | |||
| Key features include: | |||
| - Simple, intuitive API for creating 3D model viewers/configurators/editors on web pages, with many built-in presets for common workflows and use-cases. | |||
| @@ -1,5 +1,9 @@ | |||
| import {setupCodePreview} from 'https://cdn.jsdelivr.net/gh/repalash/example-code-previewer/dist/index.js'; | |||
| const rootPath = 'https://threepipe.org/' | |||
| const examplePath = 'examples/' | |||
| const codePath = 'https://github.com/repalash/threepipe/tree/master/' | |||
| const exampleScript = document.getElementById('example-script') | |||
| const scripts = exampleScript && exampleScript.dataset.scripts ? exampleScript.dataset.scripts.split(';') : [] | |||
| if(exampleScript.textContent) scripts.push(exampleScript) | |||
| @@ -7,17 +11,19 @@ const exampleStyle = document.querySelector('#example-style') | |||
| const css = exampleStyle ? exampleStyle.textContent : '' | |||
| const importMap = document.querySelector('script[type="importmap"]') | |||
| const imports = JSON.parse(importMap.textContent||'{}').imports||{} | |||
| imports['threepipe'] = 'https://threepipe.org/dist/index.mjs' | |||
| Object.entries(imports).forEach(([k,v])=>imports[k] = v.replace(/^\.\/\.\.\/\.\.\//, rootPath)) // ./../../ -> rootPath | |||
| function replaceImports(code) { | |||
| for (const [name, link] of Object.entries(imports)) code = code.replaceAll(` from '${name}'`, ` from '${link}'`) | |||
| return code | |||
| .replaceAll(` from '../../`, ` from '${rootPath}`) | |||
| .replaceAll(` from '../`, ` from '${rootPath+examplePath}`) | |||
| } | |||
| setupCodePreview( | |||
| document.getElementById('canvas-container') || document.querySelector('.code-preview-container'), | |||
| scripts, | |||
| scripts.map(s=>s.textContent ? 'js' : s.split('.').pop()), // title | |||
| scripts.map(s=>(typeof s === 'string' && s.endsWith('.js')) ? s : 'https://github.com/repalash/threepipe/tree/master/examples/'+ window.location.pathname.split('/examples/').pop().replace('index.html', '')+(s.textContent ? 'index.html' : s)), // todo: github link | |||
| (c) => '// Threepipe example: ' + window.location.href + '\n' + replaceImports(c).replaceAll(` from '../`, ` from 'https://threepipe.org/examples/`), | |||
| scripts.map(s=>(typeof s === 'string' && s.endsWith('.js')) ? s : (codePath+examplePath+window.location.pathname.split('/examples/').pop().replace('index.html', '')+(s.textContent ? 'index.html' : s))), // todo: github link | |||
| (c) => '// Threepipe example: ' + window.location.href + '\n' + replaceImports(c), | |||
| { | |||
| title: 'ThreePipe: ' + document.title, | |||
| css, | |||
| @@ -1,12 +1,12 @@ | |||
| { | |||
| "name": "threepipe", | |||
| "version": "0.0.8-dev.1", | |||
| "version": "0.0.8", | |||
| "lockfileVersion": 2, | |||
| "requires": true, | |||
| "packages": { | |||
| "": { | |||
| "name": "threepipe", | |||
| "version": "0.0.8-dev.1", | |||
| "version": "0.0.8", | |||
| "license": "Apache-2.0", | |||
| "dependencies": { | |||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1011/package.tgz", | |||
| @@ -20,7 +20,6 @@ | |||
| "@rollup/plugin-node-resolve": "^15.0.2", | |||
| "@rollup/plugin-terser": "^0.4.3", | |||
| "@rollup/plugin-typescript": "^11.1.1", | |||
| "@tweakpane/core": "1.1.8", | |||
| "@types/stats.js": "^0.17.0", | |||
| "@typescript-eslint/eslint-plugin": "^5.59.7", | |||
| "@typescript-eslint/parser": "^5.59.5", | |||
| @@ -40,7 +39,6 @@ | |||
| "stats.js": "^0.17.0", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz", | |||
| "tslib": "^2.5.0", | |||
| "tweakpane": "^3.1.9", | |||
| "typedoc": "^0.24.7", | |||
| "typescript": "^5.0.4", | |||
| "typescript-plugin-css-modules": "^5.0.1", | |||
| @@ -557,12 +555,6 @@ | |||
| "node": ">=10.13.0" | |||
| } | |||
| }, | |||
| "node_modules/@tweakpane/core": { | |||
| "version": "1.1.8", | |||
| "resolved": "https://registry.npmjs.org/@tweakpane/core/-/core-1.1.8.tgz", | |||
| "integrity": "sha512-psvBf6Cbm3YSZOTmDFWkcGzHYMnw7gVZM3jw+TfbzErIC+sMXPQb85h4ayW04w2u7AGg8jD0gHXSCg5wd+rafg==", | |||
| "dev": true | |||
| }, | |||
| "node_modules/@tweenjs/tween.js": { | |||
| "version": "18.6.4", | |||
| "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz", | |||
| @@ -9607,15 +9599,6 @@ | |||
| "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", | |||
| "dev": true | |||
| }, | |||
| "node_modules/tweakpane": { | |||
| "version": "3.1.9", | |||
| "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-3.1.9.tgz", | |||
| "integrity": "sha512-vMzh3X8uHo9HDY+9S9V0bc+UBScs8VYmMeOEW+BvynczV0aiLHweYv4eKpyoqpcRrQlkLhUsx8Dvv/1/qiCESg==", | |||
| "dev": true, | |||
| "funding": { | |||
| "url": "https://github.com/sponsors/cocopon" | |||
| } | |||
| }, | |||
| "node_modules/type-check": { | |||
| "version": "0.4.0", | |||
| "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", | |||
| @@ -10688,12 +10671,6 @@ | |||
| "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", | |||
| "dev": true | |||
| }, | |||
| "@tweakpane/core": { | |||
| "version": "1.1.8", | |||
| "resolved": "https://registry.npmjs.org/@tweakpane/core/-/core-1.1.8.tgz", | |||
| "integrity": "sha512-psvBf6Cbm3YSZOTmDFWkcGzHYMnw7gVZM3jw+TfbzErIC+sMXPQb85h4ayW04w2u7AGg8jD0gHXSCg5wd+rafg==", | |||
| "dev": true | |||
| }, | |||
| "@tweenjs/tween.js": { | |||
| "version": "18.6.4", | |||
| "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz", | |||
| @@ -17281,12 +17258,6 @@ | |||
| } | |||
| } | |||
| }, | |||
| "tweakpane": { | |||
| "version": "3.1.9", | |||
| "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-3.1.9.tgz", | |||
| "integrity": "sha512-vMzh3X8uHo9HDY+9S9V0bc+UBScs8VYmMeOEW+BvynczV0aiLHweYv4eKpyoqpcRrQlkLhUsx8Dvv/1/qiCESg==", | |||
| "dev": true | |||
| }, | |||
| "type-check": { | |||
| "version": "0.4.0", | |||
| "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "name": "threepipe", | |||
| "version": "0.0.8-dev.1", | |||
| "version": "0.0.8", | |||
| "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | |||
| "main": "src/index.ts", | |||
| "module": "dist/index.mjs", | |||
| @@ -17,7 +17,8 @@ | |||
| "serve-docs": "ws -d docs -p 8080", | |||
| "serve": "ws -d . -p 9229", | |||
| "docs": "npx typedoc && markdown-to-html", | |||
| "prepare": "npm run build && npm run build-examples" | |||
| "build-plugins": "node scripts/build-plugins.mjs", | |||
| "prepare": "npm run build && npm run build-plugins && npm run build-examples" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| @@ -89,8 +90,6 @@ | |||
| "stats.js": "^0.17.0", | |||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz", | |||
| "tslib": "^2.5.0", | |||
| "tweakpane": "^3.1.9", | |||
| "@tweakpane/core": "1.1.8", | |||
| "typedoc": "^0.24.7", | |||
| "typescript": "^5.0.4", | |||
| "typescript-plugin-css-modules": "^5.0.1", | |||
| @@ -19,7 +19,7 @@ | |||
| ], | |||
| "replace": { | |||
| "dependencies": { | |||
| "threepipe": "^0.0.8-dev.1", | |||
| "threepipe": "^0.0.8", | |||
| "@threepipe/plugin-tweakpane": "^0.1.0" | |||
| } | |||
| } | |||
| @@ -33,6 +33,8 @@ | |||
| "src" | |||
| ], | |||
| "scripts": { | |||
| "new:pack": "npm run prepare && clean-package && npm pack && clean-package restore", | |||
| "new:publish": "npm run prepare && clean-package && npm publish --access public && clean-package restore", | |||
| "prepare": "npm run build", | |||
| "build": "rimraf dist && NODE_ENV=production rollup -c", | |||
| "dev": "rollup -c -w" | |||
| @@ -9,43 +9,22 @@ | |||
| "dependencies": { | |||
| "threepipe": "file:./../../src/" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| "clean-package", | |||
| "scripts", | |||
| "devDependencies", | |||
| "//", | |||
| "markdown-to-html" | |||
| ], | |||
| "replace": { | |||
| "dependencies": { | |||
| "threepipe": "^0.0.8-dev.1" | |||
| } | |||
| } | |||
| }, | |||
| "type": "module", | |||
| "main": "dist/index.js", | |||
| "module": "dist/index.mjs", | |||
| "types": "dist/index.d.ts", | |||
| "source": "src/index.ts", | |||
| "files": [ | |||
| "dist", | |||
| "src" | |||
| ], | |||
| "scripts": { | |||
| "new:pack": "npm run prepare && clean-package && npm pack && clean-package restore", | |||
| "new:publish": "npm run prepare && clean-package && npm publish --access public && clean-package restore", | |||
| "prepare": "npm run build", | |||
| "build": "rimraf dist && NODE_ENV=production rollup -c", | |||
| "dev": "rollup -c -w" | |||
| }, | |||
| "//": { | |||
| "dependencies": { | |||
| "tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.404/package.tgz", | |||
| "uiconfig-tweakpane": "^0.0.4" | |||
| }, | |||
| "local_dependencies": { | |||
| "tweakpane-image-plugin": "file:./../tweakpane-image-plugin", | |||
| "uiconfig-tweakpane": "^file:./../uiconfig-tweakpane" | |||
| } | |||
| }, | |||
| "author": "repalash <palash@shaders.app>", | |||
| "license": "Apache-2.0", | |||
| "keywords": [ | |||
| @@ -62,5 +41,29 @@ | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/repalash/threepipe.git" | |||
| }, | |||
| "clean-package": { | |||
| "remove": [ | |||
| "clean-package", | |||
| "scripts", | |||
| "devDependencies", | |||
| "//", | |||
| "markdown-to-html" | |||
| ], | |||
| "replace": { | |||
| "dependencies": { | |||
| "threepipe": "^0.0.8" | |||
| } | |||
| } | |||
| }, | |||
| "//": { | |||
| "dependencies": { | |||
| "tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.404/package.tgz", | |||
| "uiconfig-tweakpane": "^0.0.4" | |||
| }, | |||
| "local_dependencies": { | |||
| "tweakpane-image-plugin": "file:./../tweakpane-image-plugin", | |||
| "uiconfig-tweakpane": "^file:./../uiconfig-tweakpane" | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,3 @@ | |||
| import {FolderApi} from 'tweakpane' | |||
| import * as TweakpaneImagePlugin from 'tweakpane-image-plugin' | |||
| import {UiConfigRendererTweakpane} from 'uiconfig-tweakpane' | |||
| import { | |||
| @@ -84,7 +83,7 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie | |||
| await p.fromJSON?.((p as any)._defaultState) | |||
| ui.uiRefresh?.(true, 'postFrame') | |||
| } | |||
| const topBtn = (ui.uiRef as FolderApi).controller_.view.element | |||
| const topBtn = (ui.uiRef as any).controller_.view.element | |||
| const opBtn = createDiv({ | |||
| innerHTML: '⋮', | |||
| classList: ['pluginOptionsButton'], | |||
| @@ -18,7 +18,6 @@ import { | |||
| upgradeTexture, | |||
| WebGLRenderTarget, | |||
| } from 'threepipe' | |||
| import type {FolderApi} from 'tweakpane' | |||
| import type {UiObjectConfig} from 'uiconfig.js' | |||
| import {TweakpaneUiPlugin} from './TweakpaneUiPlugin' | |||
| @@ -277,7 +276,7 @@ async function imageFromUrl(renderer: TweakpaneUiPlugin, config: UiObjectConfig, | |||
| } | |||
| } | |||
| export const tpImageInputGenerator = (viewer: ThreeViewer) => (parent: FolderApi, config: UiObjectConfig, renderer: TweakpaneUiPlugin, params?: any) => { | |||
| export const tpImageInputGenerator = (viewer: ThreeViewer) => (parent: any /* FolderApi */, config: UiObjectConfig, renderer: TweakpaneUiPlugin, params?: any) => { | |||
| // if (config.value !== undefined) throw 'Not supported yet' | |||
| if (!config.__proxy) { | |||
| @@ -0,0 +1,4 @@ | |||
| import {execEachPlugin} from "./utils.mjs"; | |||
| // Each plugin should have "prepare" that will also build the plugin | |||
| execEachPlugin('npm install') // install dependencies | |||
| @@ -0,0 +1,24 @@ | |||
| import path from "node:path"; | |||
| import fs from "node:fs"; | |||
| import {execSync} from "node:child_process"; | |||
| export function loopPluginDirs(callback){ | |||
| const __dirname = path.dirname(new URL(import.meta.url).pathname); | |||
| const pluginsDir = path.join(__dirname, '../plugins') | |||
| const pluginFolders = fs.readdirSync(pluginsDir) | |||
| for (const pluginFolder of pluginFolders) { | |||
| const pluginDir = path.join(pluginsDir, pluginFolder) | |||
| const packageJsonPath = path.join(pluginDir, 'package.json') | |||
| if (!fs.existsSync(packageJsonPath)) continue; | |||
| console.log(`NPM install ${pluginFolder}...`) | |||
| callback(pluginDir) | |||
| } | |||
| } | |||
| export function execEachPlugin(command){ | |||
| loopPluginDirs((pluginDir) => { | |||
| execSync(command, {cwd: pluginDir, stdio: 'inherit'}) | |||
| }) | |||
| } | |||