diff --git a/src/body.ts b/src/body.ts index cc5dbe6..df3d7dc 100644 --- a/src/body.ts +++ b/src/body.ts @@ -2,8 +2,6 @@ import * as THREE from 'three' import { Object3D } from 'three' import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils' import type { TupleToUnion } from 'type-fest' -import handFBXFileUrl from '../models/hand.fbx?url' -import footFBXFileUrl from '../models/foot.fbx?url' import { LoadFBXFile, LoadGLTFile, LoadObjFile } from './loader' import { FindObjectItem, @@ -11,6 +9,7 @@ import { GetWorldPosition, } from './three-utils' import { CCDIKSolver } from './CCDIKSolver' +import assets from 'environments/assets' const coco_body_keypoints_const = [ 'nose', @@ -537,6 +536,7 @@ const ExtremitiesMapping: Record< right_foot: footModelInfo, } export async function LoadHand(onLoading?: (loaded: number) => void) { + const handFBXFileUrl = assets['models/hand.fbx'] const fbx = await LoadFBXFile(handFBXFileUrl, onLoading) // fbx.scale.multiplyScalar(10) @@ -569,6 +569,7 @@ export async function LoadHand(onLoading?: (loaded: number) => void) { } export async function LoadFoot(onLoading?: (loaded: number) => void) { + const footFBXFileUrl = assets['models/foot.fbx'] const fbx = await LoadFBXFile(footFBXFileUrl, onLoading) console.log(fbx) @@ -1448,8 +1449,6 @@ export const PartIndexMappingOfBlazePoseModel = { right_foot_index: 32, } -const PosesLibraryUrl = new URL('./poses/data.bin', import.meta.url).href - const PosesLibrary: [number, number, number][][] | null = [] function getRandomInt(min: number, max: number) { @@ -1465,6 +1464,7 @@ export function GetRandomPose() { } export async function LoadPosesLibrary() { + const PosesLibraryUrl = assets['src/poses/data.bin'] const response = await fetch(PosesLibraryUrl) const buffer = await response.arrayBuffer() diff --git a/src/config.ts b/src/config.ts index 7563478..5c06281 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,4 @@ +import { setBackgroundImage } from 'environments/image' import i18n from './i18n' import { uploadImage } from './util' @@ -8,8 +9,6 @@ export const options: Record = { Height: 0, async setBackground() { const dataUrl = await uploadImage() - const div = document.getElementById('background') - - if (div) div.style.backgroundImage = `url(${dataUrl})` + setBackgroundImage(dataUrl) }, } diff --git a/src/editor.ts b/src/editor.ts index f354ed7..a5423aa 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -38,13 +38,11 @@ import { PartIndexMappingOfBlazePoseModel, } from './body' import { options } from './config' -import { SetScreenShot } from './image' import { download, downloadJson, getCurrentTime, getImage, - setBackgroundImage, uploadImage, uploadJson, } from './util' @@ -60,6 +58,11 @@ import Swal from 'sweetalert2' import i18n from './i18n' import { FindObjectItem } from './three-utils' import { DetectPosefromImage } from './detect' +import { + onMakeImages, + setBackgroundImage, + SetScreenShot, +} from 'environments/image' interface BodyData { position: ReturnType @@ -131,7 +134,7 @@ export class BodyEditor { alight: THREE.AmbientLight raycaster = new THREE.Raycaster() IsClick = false - stats: Stats + stats: Stats | undefined // ikSolver?: CCDIKSolver composer?: EffectComposer @@ -139,7 +142,7 @@ export class BodyEditor { enableComposer = false enablePreview = true - constructor(canvas: HTMLCanvasElement) { + constructor(canvas: HTMLCanvasElement, statsElem?: Element) { this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true, @@ -228,8 +231,10 @@ export class BodyEditor { // // Setup post-processing step // this.setupPost(); - this.stats = Stats() - document.body.appendChild(this.stats.dom) + if (statsElem) { + this.stats = Stats() + statsElem.appendChild(this.stats.dom) + } this.animate() this.handleResize() this.AutoSaveScene() @@ -463,7 +468,7 @@ export class BodyEditor { this.handleResize() this.render() if (this.enablePreview) this.renderPreview() - this.stats.update() + this.stats?.update() } getAncestors(o: Object3D) { @@ -861,6 +866,8 @@ export class BodyEditor { this.renderer.setClearColor(0x000000, 0) this.axesHelper.visible = true this.gridHelper.visible = true + + onMakeImages() } CopySelectedBody() { diff --git a/src/environments/online/assets.ts b/src/environments/online/assets.ts new file mode 100644 index 0000000..e82c492 --- /dev/null +++ b/src/environments/online/assets.ts @@ -0,0 +1,9 @@ +import handFBXFileUrl from '../../../models/hand.fbx?url' +import footFBXFileUrl from '../../../models/foot.fbx?url' +const PosesLibraryUrl = new URL('../../poses/data.bin', import.meta.url).href + +export default { + 'models/hand.fbx': handFBXFileUrl, + 'models/foot.fbx': footFBXFileUrl, + 'src/poses/data.bin': PosesLibraryUrl, +} diff --git a/src/environments/online/gui.ts b/src/environments/online/gui.ts new file mode 100644 index 0000000..ba3b41b --- /dev/null +++ b/src/environments/online/gui.ts @@ -0,0 +1,10 @@ +import * as dat from 'dat.gui' + +export const canvasElement = + document.querySelector('#canvas')! +export const statsElement = document.body + +export function createDatGui() { + const gui = new dat.GUI() + return gui +} diff --git a/src/image.ts b/src/environments/online/image.ts similarity index 56% rename from src/image.ts rename to src/environments/online/image.ts index 6bf524c..4e7dde8 100644 --- a/src/image.ts +++ b/src/environments/online/image.ts @@ -1,4 +1,4 @@ -import { download } from './util' +import { download } from '../../util' document.querySelectorAll('.gallery img').forEach((img) => img.addEventListener('click', (e) => { @@ -17,3 +17,15 @@ export function SetScreenShot(id: string, url: string, name: string) { img.title = name } } + +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function onMakeImages() {} + +export function setBackgroundImage(dataUrl: string | null) { + const div = document.getElementById('background') + + if (div) { + if (!dataUrl) div.style.backgroundImage = 'none' + else div.style.backgroundImage = `url(${dataUrl})` + } +} diff --git a/src/index.css b/src/environments/online/index.css similarity index 100% rename from src/index.css rename to src/environments/online/index.css diff --git a/src/init.ts b/src/environments/online/init.ts similarity index 100% rename from src/init.ts rename to src/environments/online/init.ts diff --git a/src/update.ts b/src/environments/online/update.ts similarity index 95% rename from src/update.ts rename to src/environments/online/update.ts index afd17a5..92e49eb 100644 --- a/src/update.ts +++ b/src/environments/online/update.ts @@ -2,7 +2,7 @@ import { registerSW } from 'virtual:pwa-register' import Swal from 'sweetalert2' -import i18n from './i18n' +import i18n from '../../i18n' async function PWAPopup(update: (reloadPage?: boolean) => Promise) { const result = await Swal.fire( diff --git a/src/main.tsx b/src/main.tsx index ce5702f..cd855e4 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,16 +1,14 @@ -import './init' -import * as dat from 'dat.gui' -import './index.css' +import 'environments/init' +import 'environments/index.css' import { options } from './config' import { BodyEditor } from './editor' import i18n from './i18n' import { CreateBodyParamsControls } from './body-params' import { CreateLanguageFolder } from './language' +import { canvasElement, createDatGui, statsElement } from 'environments/gui' -const editor = new BodyEditor( - document.querySelector('#canvas')! -) -const gui = new dat.GUI() +const editor = new BodyEditor(canvasElement, statsElement) +const gui = createDatGui() window.addEventListener('keydown', function (event) { switch (event.code) { @@ -60,8 +58,10 @@ edit.add(editor, 'RemoveBody').name(i18n.t('Delete Skeleton (Del)')) const setting = gui.addFolder(i18n.t('Setting')) -options['Width'] = editor.Width -options['Height'] = editor.Height +if (options['Width'] == 0 || options['Height'] == 0) { + options['Width'] = editor.Width + options['Height'] = editor.Height +} setting .add(options, 'Width', 128, 5000) .name(i18n.t('Width')) @@ -116,3 +116,5 @@ window.addEventListener('resize', () => { }) editor.loadBodyData() + +export { editor } diff --git a/src/util.ts b/src/util.ts index 53d1e73..d1a138e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -33,12 +33,6 @@ export function getImage(url: string): Promise { }) } -export function setBackgroundImage(dataUrl: string) { - const div = document.getElementById('background') - - if (div) div.style.backgroundImage = `url(${dataUrl})` -} - export function getCurrentTime(format = 'YYYY_MM_DD_HH_mm_ss') { return dayjs(new Date()).format(format) } diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 575cfee..2de3ceb 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -2,3 +2,21 @@ declare const __APP_VERSION__: string declare const __APP_BUILD_TIME__: number +declare module 'environments/gui' { + export const canvasElement: HTMLCanvasElement + export const statsElement: HTMLElement | undefined + export function createDatGui(): dat.GUI +} +declare module 'environments/assets' { + export = { + 'models/hand.fbx': string, + 'models/foot.fbx': string, + 'src/poses/data.bin': string, + } +} +declare module 'environments/image' { + export function SetScreenShot(id: string, url: string, name: string): void + export function onMakeImages(): void + export function setBackgroundImage(dataUrl: string | null): void +} +declare module 'environments/init' {} diff --git a/vite.config.ts b/vite.config.ts index 8d7cbee..ee3af87 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,29 +1,42 @@ -import { defineConfig } from 'vite' +import { defineConfig, type UserConfigExport } from 'vite' import react from '@vitejs/plugin-react' import { VitePWA } from 'vite-plugin-pwa' -import { visualizer } from "rollup-plugin-visualizer" +import { visualizer } from 'rollup-plugin-visualizer' +import { resolve } from 'path' // https://vitejs.dev/config/ -export default defineConfig({ +const config: UserConfigExport = { base: '/open-pose-editor/', define: { global: {}, - __APP_VERSION__: JSON.stringify("v0.0.2"), - __APP_BUILD_TIME__: Date.now() + __APP_VERSION__: JSON.stringify('v0.0.2'), + __APP_BUILD_TIME__: Date.now(), }, - build: { - }, - plugins: [react(), VitePWA({ - workbox: { - globPatterns: ['**/*.{js,css,html,ico,png,svg,mp3,obj,fbx,bin}'] + build: {}, + resolve: { + alias: { + 'environments': resolve(__dirname, 'src/environments/online/'), }, - manifest: { - name: 'open pose editor', - short_name: 'open pose editor', - description: 'open pose editor (Yu Zhu)', - theme_color: "#ffffff", - background_color: "#ffffff", - display: "standalone", - } - }), visualizer()], -}) + }, + plugins: [ + react(), + VitePWA({ + workbox: { + globPatterns: [ + '**/*.{js,css,html,ico,png,svg,mp3,obj,fbx,bin}', + ], + }, + manifest: { + name: 'open pose editor', + short_name: 'open pose editor', + description: 'open pose editor (Yu Zhu)', + theme_color: '#ffffff', + background_color: '#ffffff', + display: 'standalone', + }, + }), + visualizer(), + ], +} + +export default defineConfig(config)