forked from lightningpixel/modly
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseApi.ts
More file actions
133 lines (116 loc) · 4.11 KB
/
Copy pathuseApi.ts
File metadata and controls
133 lines (116 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import axios from 'axios'
import { useAppStore, GenerationOptions } from '@shared/stores/appStore'
export function useApi() {
const apiUrl = useAppStore((s) => s.apiUrl)
const client = axios.create({ baseURL: apiUrl })
async function generateFromImage(
imagePath: string,
options: GenerationOptions,
imageData?: string,
signal?: AbortSignal,
): Promise<{ jobId: string }> {
// Use provided base64 (drag & drop) or read from disk via IPC
const base64 = imageData ?? await window.electron.fs.readFileBase64(imagePath)
const byteArray = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0))
const blob = new Blob([byteArray], { type: 'image/png' })
const filename = imagePath.split(/[\\/]/).pop() ?? 'image.png'
const formData = new FormData()
formData.append('image', blob, filename)
formData.append('model_id', options.modelId)
formData.append('remesh', options.remesh)
formData.append('enable_texture', String(options.enableTexture))
formData.append('texture_resolution', String(options.textureResolution))
formData.append('params', JSON.stringify(options.modelParams))
const { data } = await client.post<{ job_id: string }>('/generate/from-image', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
signal,
})
return { jobId: data.job_id }
}
async function pollJobStatus(jobId: string): Promise<{
status: 'pending' | 'running' | 'done' | 'error' | 'cancelled'
progress: number
step?: string
outputUrl?: string
error?: string
}> {
const { data } = await client.get(`/generate/status/${jobId}`)
return { ...data, outputUrl: data.output_url }
}
async function getModelStatus(): Promise<{
downloaded: boolean
name: string
size_gb: number
progress?: number
}> {
const { data } = await client.get('/model/status')
return data
}
async function getAllModelsStatus(): Promise<{ id: string; name: string; downloaded: boolean }[]> {
const { data } = await client.get('/model/all')
return data
}
async function downloadModel(
onProgress?: (pct: number) => void
): Promise<void> {
const response = await client.get('/model/download', {
responseType: 'stream'
})
const reader = response.data
reader.on('data', (chunk: Buffer) => {
try {
const line = chunk.toString().replace('data: ', '').trim()
if (line) {
const { progress } = JSON.parse(line)
onProgress?.(progress)
}
} catch {
// ignore parse errors
}
})
await new Promise<void>((resolve, reject) => {
reader.on('end', resolve)
reader.on('error', reject)
})
}
async function optimizeMesh(
path: string,
targetFaces: number,
): Promise<{ url: string; faceCount: number }> {
const { data } = await client.post<{ url: string; face_count: number }>('/optimize/mesh', {
path,
target_faces: targetFaces,
})
return { url: data.url, faceCount: data.face_count }
}
async function cancelJob(jobId: string): Promise<void> {
await client.post(`/generate/cancel/${jobId}`).catch(() => {})
}
async function smoothMesh(
path: string,
iterations: number,
): Promise<{ url: string }> {
const { data } = await client.post<{ url: string }>('/optimize/smooth', {
path,
iterations,
})
return { url: data.url }
}
async function importMesh(filePath: string): Promise<{ url: string }> {
const { data } = await client.post<{ url: string }>('/optimize/import-by-path', { path: filePath })
return { url: data.url }
}
// Bakes a world-space 4x4 transform into the GLB geometry.
// `matrix` is row-major (4 rows of 4), matching the backend's reshape.
async function transformMesh(
path: string,
matrix: number[][],
): Promise<{ url: string }> {
const { data } = await client.post<{ url: string }>('/optimize/transform', {
path,
matrix,
})
return { url: data.url }
}
return { generateFromImage, pollJobStatus, cancelJob, getModelStatus, getAllModelsStatus, downloadModel, optimizeMesh, smoothMesh, importMesh, transformMesh }
}