From 69018c8b366ff2c973eecb8a9e294f7a0cd0fbac Mon Sep 17 00:00:00 2001 From: julio Date: Tue, 6 Oct 2026 02:19:19 -0300 Subject: [PATCH] feat(reacoes): emojis e figurinhas no mesmo padrao do rosto novo - rosto-motor.js desenha emoji e figurinha dentro dos olhos no estilo e formato escolhidos (brilho, piscada; na Lente no lugar da iris; na Matriz os LEDs usam as cores do desenho) - MotorRosto.retrato desenha um retrato parado em qualquer canvas - miniaturas da biblioteca no painel usam o mesmo motor, no rosto, formato e cor atuais do robo (3:2, com o simbolo "ao redor" no canto) - emoji e figurinha "ao redor" ganham o brilho na cor da reacao - cartoes da biblioteca com as acoes numa linha so Co-Authored-By: Claude Opus 5.5 --- android/app/assets/carinha.html | 4 +- android/app/assets/rosto-motor.js | 74 ++++++++++++++++++- carinha.html | 4 +- reacoes-render.js | 4 +- rosto-motor.js | 74 ++++++++++++++++++- web/index.html | 2 + web/src/lib/componentes/Miniatura.svelte | 94 +++++++++++++++--------- web/src/telas/Reacoes.svelte | 8 ++ web/vite.config.ts | 2 +- 9 files changed, 220 insertions(+), 46 deletions(-) diff --git a/android/app/assets/carinha.html b/android/app/assets/carinha.html index a1b574a..26cfed2 100644 --- a/android/app/assets/carinha.html +++ b/android/app/assets/carinha.html @@ -388,11 +388,13 @@ function desenhar() { const mover = seguindo ? .55 : (r.kf !== null || r.dormindo) ? 0.25 : (mirando ? 0.25 : 0.0); const dx = seguindo ? MOV.olharX : r.dx, dy = seguindo ? MOV.olharY : r.dy; const olhos = [[E1, ab, r.forma, +1], [E2, ab2, f2, -1]]; - const comMotor = ROSTO.motor && window.MotorRosto && !window.carinhaOlhosIcone && !window.carinhaOlhosDesenho; + const comMotor = ROSTO.motor && window.MotorRosto; OLHOS.forEach((g) => { g.style.display = comMotor ? "none" : ""; }); if (comMotor) { window.MotorRosto.desenhar({ estilo: ROSTO.motor, formato: FORMATO, t: tAgora, cor: r.cor, dormindo: r.dormindo, + icone: !r.dormindo && !window.carinhaOlhosDesenho ? window.carinhaOlhosIcone || null : null, + desenho: !r.dormindo ? window.carinhaOlhosDesenho || null : null, parado: !r.kf && !seguindo && !r.dormindo, olhos: olhos.map(([c, abx, fx, lado]) => ({ cx: c[0] + dx * mover * ESC, cy: c[1] + dy * mover * ESC, ry: RY * esc, diff --git a/android/app/assets/rosto-motor.js b/android/app/assets/rosto-motor.js index 74b5d1e..ea0cd4a 100644 --- a/android/app/assets/rosto-motor.js +++ b/android/app/assets/rosto-motor.js @@ -82,9 +82,35 @@ c.fill(); } + const FONTE_EMOJI = '"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif'; + + /** Figurinha (viewBox 100x100, só M L C Q Z) ou emoji, centrado no olho. */ + function conteudo(c, o, cx, cy, tam) { + if (o.desenho && Array.isArray(o.desenho.formas)) { + c.save(); + c.translate(cx - tam / 2, cy - tam / 2); + c.scale(tam / 100, tam / 100); + for (const f of o.desenho.formas) { + if (typeof f.caminho !== 'string' || !/^[MLCQZmlcqz0-9.,\s+-]+$/.test(f.caminho) || !/^#[0-9a-f]{6}$/i.test(f.cor)) continue; + c.fillStyle = f.cor; + c.fill(new Path2D(f.caminho)); + } + c.restore(); + } else if (o.icone) { + c.save(); + c.font = Math.round(tam * 0.8) + 'px ' + FONTE_EMOJI; + c.textAlign = 'center'; + c.textBaseline = 'middle'; + c.fillText(o.icone, cx, cy + tam * 0.04); + c.restore(); + } + } + // Olho plano (vivo, bloco, matriz): corpo + pálpebras recortadas (transparentes). function olhoPlano(c, o, p, est, e) { const respira = 1 + 0.012 * Math.sin(o.t * 1.4); + const temConteudo = !!(o.icone || o.desenho); + if (temConteudo) e = { top: 0, slant: 0, bot: 0, coracao: 0 }; const fecha = Math.min(1, Math.max(e.top, 1 - Math.min(1, p.ab))); const abre = Math.max(1, p.ab); // surpreso abre além de 1 const amassa = fecha > 0.5 && e.top < 0.5 ? (fecha - 0.5) * 0.2 : 0; // piscada achata e alarga @@ -105,7 +131,8 @@ c.beginPath(); c.moveTo(x - 4, y - 4); c.lineTo(x + w + 4, y - 4); c.lineTo(x + w + 4, yDir); c.lineTo(x - 4, yEsq); c.closePath(); c.fill(); c.beginPath(); c.ellipse(p.cx, y + h * (1.62 - e.bot), w * 0.75, h * 0.62, 0, 0, Math.PI * 2); c.fill(); c.globalCompositeOperation = 'source-over'; - if (est.brilho && fecha < 0.55 && e.bot < 0.3) { // reflexo que acompanha o olhar + if (temConteudo && fecha < 0.6) conteudo(c, o, p.cx, p.cy, Math.min(w, h) * 0.74); + else if (est.brilho && fecha < 0.55 && e.bot < 0.3) { // reflexo que acompanha o olhar const hx = Math.max(x + w * 0.18, Math.min(x + w * 0.62, x + w * 0.3 + (p.lx + sacada.x) * w * 0.012)); const hy = Math.max(y + h * 0.18, Math.min(y + h * 0.5, y + h * 0.26 + (p.ly + sacada.y) * h * 0.012)); c.fillStyle = 'rgba(245,250,255,0.9)'; @@ -117,11 +144,15 @@ // Olho lente: esclera, íris, pupila que dilata e pálpebras de metal. function olhoLente(c, o, p, est, e) { const R = est.w * p.ry * 0.5 * Math.max(1, p.ab) * (1 + 0.01 * Math.sin(o.t * 1.4)); - const fecha = Math.min(1, Math.max(e.top, 1 - Math.min(1, p.ab))); + const fecha = Math.min(1, Math.max(o.icone || o.desenho ? 0 : e.top, 1 - Math.min(1, p.ab))); c.save(); c.beginPath(); c.arc(p.cx, p.cy, R * 1.12, 0, Math.PI * 2); c.fillStyle = '#1b2029'; c.fill(); c.beginPath(); c.arc(p.cx, p.cy, R, 0, Math.PI * 2); c.clip(); c.fillStyle = '#e9eef3'; c.fillRect(p.cx - R, p.cy - R, 2 * R, 2 * R); + if (o.icone || o.desenho) { + conteudo(c, o, p.cx, p.cy, R * 1.3); + e = { top: 0, slant: 0, bot: 0 }; + } else { const ix = p.cx + Math.max(-R * 0.4, Math.min(R * 0.4, (p.lx + sacada.x) * R * 0.02)); const iy = p.cy + Math.max(-R * 0.35, Math.min(R * 0.35, (p.ly + sacada.y) * R * 0.02)); const g = c.createRadialGradient(ix, iy, R * 0.05, ix, iy, R * 0.55); @@ -130,6 +161,7 @@ const pupila = p.ab > 1.05 ? 0.12 : e.bot > 0.3 ? 0.3 : 0.2; // susto contrai, alegria dilata c.beginPath(); c.arc(ix, iy, R * pupila, 0, Math.PI * 2); c.fillStyle = '#05070a'; c.fill(); c.beginPath(); c.arc(ix - R * 0.2, iy - R * 0.22, R * 0.09, 0, Math.PI * 2); c.fillStyle = 'rgba(255,255,255,0.9)'; c.fill(); + } const metal = c.createLinearGradient(0, p.cy - R, 0, p.cy + R); metal.addColorStop(0, '#5b6675'); metal.addColorStop(1, '#2b323d'); c.fillStyle = metal; @@ -180,7 +212,7 @@ for (let j = 0; j < linhas; j++) for (let i = 0; i < colunas; i++) { const k = (j * colunas + i) * 4, a = px[k + 3] / 255; ctx.beginPath(); ctx.arc((i + 0.5) * passo, (j + 0.5) * passo, raio, 0, Math.PI * 2); - ctx.fillStyle = a > 0.25 ? css(o.cor, 0.35 + a * 0.65) : 'rgba(255,255,255,0.045)'; + ctx.fillStyle = a > 0.25 ? css([px[k], px[k + 1], px[k + 2]], 0.35 + a * 0.65) : 'rgba(255,255,255,0.045)'; ctx.fill(); } } @@ -217,7 +249,41 @@ ctx.restore(); } + /** + * Retrato parado num canvas qualquer (miniaturas da biblioteca no painel). + * o = { estilo, formato, cor, forma, icone, desenho }. + */ + function retrato(alvo, o) { + const base = ESTILOS[o.estilo] || ESTILOS.vivo; + const formato = !base.lente && FORMATOS[o.formato]; + const est = formato ? Object.assign({}, base, formato) : base; + const W = alvo.width, H = alvo.height, c = alvo.getContext('2d'); + const pal = Object.assign({ coracao: o.forma === 'coracao' ? 1 : 0 }, PALPEBRAS[o.forma] || PALPEBRAS.aberto); + const op = { t: 0, cor: o.cor || [92, 214, 255], icone: o.icone || null, desenho: o.desenho || null }; + const ry = H * 0.36, sep = Math.min(W * 0.23, H * 0.62); + const olhos = [-1, 1].map((s) => ({ cx: W / 2 + s * sep, cy: H / 2, ry, ab: o.forma === 'surpreso' ? 1.12 : 1, forma: o.forma, lado: -s, lx: 0, ly: 0 })); + c.clearRect(0, 0, W, H); + if (est.lente) { olhos.forEach((p) => olhoLente(c, op, p, est, pal)); return; } + const tmp = document.createElement('canvas'); tmp.width = W; tmp.height = H; + const t = tmp.getContext('2d'); + olhos.forEach((p) => olhoPlano(t, op, p, est, Object.assign({}, pal))); + if (est.pontos) { + const passo = Math.max(3, Math.round(H / 16)), d = t.getImageData(0, 0, W, H).data; + for (let y = passo / 2; y < H; y += passo) for (let x = passo / 2; x < W; x += passo) { + const k = (Math.floor(y) * W + Math.floor(x)) * 4, a = d[k + 3] / 255; + c.beginPath(); c.arc(x, y, passo * 0.38, 0, Math.PI * 2); + c.fillStyle = a > 0.25 ? css([d[k], d[k + 1], d[k + 2]], 0.4 + a * 0.6) : 'rgba(255,255,255,0.05)'; + c.fill(); + } + return; + } + c.save(); + if (est.brilho) { c.shadowColor = css(op.cor, 0.7); c.shadowBlur = H * 0.08; } + c.drawImage(tmp, 0, 0); + c.restore(); + } + function esconder() { if (tela) tela.style.display = 'none'; antes = 0; } - window.MotorRosto = { desenhar, esconder, estilos: Object.keys(ESTILOS), formatos: Object.keys(FORMATOS) }; + window.MotorRosto = { desenhar, retrato, esconder, estilos: Object.keys(ESTILOS), formatos: Object.keys(FORMATOS) }; })(); diff --git a/carinha.html b/carinha.html index a1b574a..26cfed2 100644 --- a/carinha.html +++ b/carinha.html @@ -388,11 +388,13 @@ function desenhar() { const mover = seguindo ? .55 : (r.kf !== null || r.dormindo) ? 0.25 : (mirando ? 0.25 : 0.0); const dx = seguindo ? MOV.olharX : r.dx, dy = seguindo ? MOV.olharY : r.dy; const olhos = [[E1, ab, r.forma, +1], [E2, ab2, f2, -1]]; - const comMotor = ROSTO.motor && window.MotorRosto && !window.carinhaOlhosIcone && !window.carinhaOlhosDesenho; + const comMotor = ROSTO.motor && window.MotorRosto; OLHOS.forEach((g) => { g.style.display = comMotor ? "none" : ""; }); if (comMotor) { window.MotorRosto.desenhar({ estilo: ROSTO.motor, formato: FORMATO, t: tAgora, cor: r.cor, dormindo: r.dormindo, + icone: !r.dormindo && !window.carinhaOlhosDesenho ? window.carinhaOlhosIcone || null : null, + desenho: !r.dormindo ? window.carinhaOlhosDesenho || null : null, parado: !r.kf && !seguindo && !r.dormindo, olhos: olhos.map(([c, abx, fx, lado]) => ({ cx: c[0] + dx * mover * ESC, cy: c[1] + dy * mover * ESC, ry: RY * esc, diff --git a/reacoes-render.js b/reacoes-render.js index 74a73f6..71c1add 100644 --- a/reacoes-render.js +++ b/reacoes-render.js @@ -15,13 +15,13 @@ function visual(recipe){ if(recipe.emoji){ const e=recipe.emoji;if(e.local==='olhos'){window.carinhaOlhosIcone=e.caractere;return;} - badge.style.cssText='position:fixed;right:5%;top:8%;z-index:15;font:clamp(42px,10vw,90px) sans-serif;pointer-events:none';badge.textContent=e.caractere; + badge.style.cssText='position:fixed;right:5%;top:8%;z-index:15;font:clamp(42px,10vw,90px) sans-serif;pointer-events:none;filter:drop-shadow(0 0 14px '+(recipe.passos[0].cor||'#5cd6ff')+')';badge.textContent=e.caractere; animation=badge.animate([{transform:'scale(.92)'},{transform:'scale(1.06)'},{transform:'scale(.92)'}],{duration:1400,iterations:Infinity});return; } if(recipe.figurinha){ const svg=window.carinhaConstruirSVG(recipe.figurinha);if(!svg)return; if(recipe.figurinha.local==='olhos'){window.carinhaOlhosDesenho=recipe.figurinha;return;} - badge.style.cssText='position:fixed;right:5%;top:8%;width:24%;height:30%;z-index:15;pointer-events:none';svg.style.cssText='width:100%;height:100%';badge.append(svg); + badge.style.cssText='position:fixed;right:5%;top:8%;width:24%;height:30%;z-index:15;pointer-events:none;filter:drop-shadow(0 0 14px '+(recipe.passos[0].cor||'#5cd6ff')+')';svg.style.cssText='width:100%;height:100%';badge.append(svg); animation=svg.animate([{transform:'scale(.92) rotate(-3deg)'},{transform:'scale(1.05) rotate(3deg)'},{transform:'scale(.92) rotate(-3deg)'}],{duration:1500,iterations:Infinity});return; } if(['ideia','cafe'].includes(recipe.simbolo)){window.carinhaOlhosIcone=icons[recipe.simbolo];return;} diff --git a/rosto-motor.js b/rosto-motor.js index 74b5d1e..ea0cd4a 100644 --- a/rosto-motor.js +++ b/rosto-motor.js @@ -82,9 +82,35 @@ c.fill(); } + const FONTE_EMOJI = '"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif'; + + /** Figurinha (viewBox 100x100, só M L C Q Z) ou emoji, centrado no olho. */ + function conteudo(c, o, cx, cy, tam) { + if (o.desenho && Array.isArray(o.desenho.formas)) { + c.save(); + c.translate(cx - tam / 2, cy - tam / 2); + c.scale(tam / 100, tam / 100); + for (const f of o.desenho.formas) { + if (typeof f.caminho !== 'string' || !/^[MLCQZmlcqz0-9.,\s+-]+$/.test(f.caminho) || !/^#[0-9a-f]{6}$/i.test(f.cor)) continue; + c.fillStyle = f.cor; + c.fill(new Path2D(f.caminho)); + } + c.restore(); + } else if (o.icone) { + c.save(); + c.font = Math.round(tam * 0.8) + 'px ' + FONTE_EMOJI; + c.textAlign = 'center'; + c.textBaseline = 'middle'; + c.fillText(o.icone, cx, cy + tam * 0.04); + c.restore(); + } + } + // Olho plano (vivo, bloco, matriz): corpo + pálpebras recortadas (transparentes). function olhoPlano(c, o, p, est, e) { const respira = 1 + 0.012 * Math.sin(o.t * 1.4); + const temConteudo = !!(o.icone || o.desenho); + if (temConteudo) e = { top: 0, slant: 0, bot: 0, coracao: 0 }; const fecha = Math.min(1, Math.max(e.top, 1 - Math.min(1, p.ab))); const abre = Math.max(1, p.ab); // surpreso abre além de 1 const amassa = fecha > 0.5 && e.top < 0.5 ? (fecha - 0.5) * 0.2 : 0; // piscada achata e alarga @@ -105,7 +131,8 @@ c.beginPath(); c.moveTo(x - 4, y - 4); c.lineTo(x + w + 4, y - 4); c.lineTo(x + w + 4, yDir); c.lineTo(x - 4, yEsq); c.closePath(); c.fill(); c.beginPath(); c.ellipse(p.cx, y + h * (1.62 - e.bot), w * 0.75, h * 0.62, 0, 0, Math.PI * 2); c.fill(); c.globalCompositeOperation = 'source-over'; - if (est.brilho && fecha < 0.55 && e.bot < 0.3) { // reflexo que acompanha o olhar + if (temConteudo && fecha < 0.6) conteudo(c, o, p.cx, p.cy, Math.min(w, h) * 0.74); + else if (est.brilho && fecha < 0.55 && e.bot < 0.3) { // reflexo que acompanha o olhar const hx = Math.max(x + w * 0.18, Math.min(x + w * 0.62, x + w * 0.3 + (p.lx + sacada.x) * w * 0.012)); const hy = Math.max(y + h * 0.18, Math.min(y + h * 0.5, y + h * 0.26 + (p.ly + sacada.y) * h * 0.012)); c.fillStyle = 'rgba(245,250,255,0.9)'; @@ -117,11 +144,15 @@ // Olho lente: esclera, íris, pupila que dilata e pálpebras de metal. function olhoLente(c, o, p, est, e) { const R = est.w * p.ry * 0.5 * Math.max(1, p.ab) * (1 + 0.01 * Math.sin(o.t * 1.4)); - const fecha = Math.min(1, Math.max(e.top, 1 - Math.min(1, p.ab))); + const fecha = Math.min(1, Math.max(o.icone || o.desenho ? 0 : e.top, 1 - Math.min(1, p.ab))); c.save(); c.beginPath(); c.arc(p.cx, p.cy, R * 1.12, 0, Math.PI * 2); c.fillStyle = '#1b2029'; c.fill(); c.beginPath(); c.arc(p.cx, p.cy, R, 0, Math.PI * 2); c.clip(); c.fillStyle = '#e9eef3'; c.fillRect(p.cx - R, p.cy - R, 2 * R, 2 * R); + if (o.icone || o.desenho) { + conteudo(c, o, p.cx, p.cy, R * 1.3); + e = { top: 0, slant: 0, bot: 0 }; + } else { const ix = p.cx + Math.max(-R * 0.4, Math.min(R * 0.4, (p.lx + sacada.x) * R * 0.02)); const iy = p.cy + Math.max(-R * 0.35, Math.min(R * 0.35, (p.ly + sacada.y) * R * 0.02)); const g = c.createRadialGradient(ix, iy, R * 0.05, ix, iy, R * 0.55); @@ -130,6 +161,7 @@ const pupila = p.ab > 1.05 ? 0.12 : e.bot > 0.3 ? 0.3 : 0.2; // susto contrai, alegria dilata c.beginPath(); c.arc(ix, iy, R * pupila, 0, Math.PI * 2); c.fillStyle = '#05070a'; c.fill(); c.beginPath(); c.arc(ix - R * 0.2, iy - R * 0.22, R * 0.09, 0, Math.PI * 2); c.fillStyle = 'rgba(255,255,255,0.9)'; c.fill(); + } const metal = c.createLinearGradient(0, p.cy - R, 0, p.cy + R); metal.addColorStop(0, '#5b6675'); metal.addColorStop(1, '#2b323d'); c.fillStyle = metal; @@ -180,7 +212,7 @@ for (let j = 0; j < linhas; j++) for (let i = 0; i < colunas; i++) { const k = (j * colunas + i) * 4, a = px[k + 3] / 255; ctx.beginPath(); ctx.arc((i + 0.5) * passo, (j + 0.5) * passo, raio, 0, Math.PI * 2); - ctx.fillStyle = a > 0.25 ? css(o.cor, 0.35 + a * 0.65) : 'rgba(255,255,255,0.045)'; + ctx.fillStyle = a > 0.25 ? css([px[k], px[k + 1], px[k + 2]], 0.35 + a * 0.65) : 'rgba(255,255,255,0.045)'; ctx.fill(); } } @@ -217,7 +249,41 @@ ctx.restore(); } + /** + * Retrato parado num canvas qualquer (miniaturas da biblioteca no painel). + * o = { estilo, formato, cor, forma, icone, desenho }. + */ + function retrato(alvo, o) { + const base = ESTILOS[o.estilo] || ESTILOS.vivo; + const formato = !base.lente && FORMATOS[o.formato]; + const est = formato ? Object.assign({}, base, formato) : base; + const W = alvo.width, H = alvo.height, c = alvo.getContext('2d'); + const pal = Object.assign({ coracao: o.forma === 'coracao' ? 1 : 0 }, PALPEBRAS[o.forma] || PALPEBRAS.aberto); + const op = { t: 0, cor: o.cor || [92, 214, 255], icone: o.icone || null, desenho: o.desenho || null }; + const ry = H * 0.36, sep = Math.min(W * 0.23, H * 0.62); + const olhos = [-1, 1].map((s) => ({ cx: W / 2 + s * sep, cy: H / 2, ry, ab: o.forma === 'surpreso' ? 1.12 : 1, forma: o.forma, lado: -s, lx: 0, ly: 0 })); + c.clearRect(0, 0, W, H); + if (est.lente) { olhos.forEach((p) => olhoLente(c, op, p, est, pal)); return; } + const tmp = document.createElement('canvas'); tmp.width = W; tmp.height = H; + const t = tmp.getContext('2d'); + olhos.forEach((p) => olhoPlano(t, op, p, est, Object.assign({}, pal))); + if (est.pontos) { + const passo = Math.max(3, Math.round(H / 16)), d = t.getImageData(0, 0, W, H).data; + for (let y = passo / 2; y < H; y += passo) for (let x = passo / 2; x < W; x += passo) { + const k = (Math.floor(y) * W + Math.floor(x)) * 4, a = d[k + 3] / 255; + c.beginPath(); c.arc(x, y, passo * 0.38, 0, Math.PI * 2); + c.fillStyle = a > 0.25 ? css([d[k], d[k + 1], d[k + 2]], 0.4 + a * 0.6) : 'rgba(255,255,255,0.05)'; + c.fill(); + } + return; + } + c.save(); + if (est.brilho) { c.shadowColor = css(op.cor, 0.7); c.shadowBlur = H * 0.08; } + c.drawImage(tmp, 0, 0); + c.restore(); + } + function esconder() { if (tela) tela.style.display = 'none'; antes = 0; } - window.MotorRosto = { desenhar, esconder, estilos: Object.keys(ESTILOS), formatos: Object.keys(FORMATOS) }; + window.MotorRosto = { desenhar, retrato, esconder, estilos: Object.keys(ESTILOS), formatos: Object.keys(FORMATOS) }; })(); diff --git a/web/index.html b/web/index.html index 155f7d3..4c0c6e5 100644 --- a/web/index.html +++ b/web/index.html @@ -9,6 +9,8 @@
+ + diff --git a/web/src/lib/componentes/Miniatura.svelte b/web/src/lib/componentes/Miniatura.svelte index 98a00e2..16546e8 100644 --- a/web/src/lib/componentes/Miniatura.svelte +++ b/web/src/lib/componentes/Miniatura.svelte @@ -1,56 +1,84 @@ diff --git a/web/src/telas/Reacoes.svelte b/web/src/telas/Reacoes.svelte index 27b06a0..b7a437c 100644 --- a/web/src/telas/Reacoes.svelte +++ b/web/src/telas/Reacoes.svelte @@ -364,6 +364,14 @@ .espaco { flex: 1; } + /* seis ações pequenas + Mostrar cabem numa linha num cartão de 300 px */ + .acoes :global(.btn.pequeno.icone) { + width: 28px; + } + .acoes { + flex-wrap: nowrap; + gap: 2px; + } .marcado { color: var(--ok); border-color: var(--ok); diff --git a/web/vite.config.ts b/web/vite.config.ts index b0b0918..48d9648 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -6,7 +6,7 @@ import { svelte } from '@sveltejs/vite-plugin-svelte'; const alvo = process.env.CARINHA_SERVIDOR || 'http://127.0.0.1:8100'; const api = ['/eventos', '/estado', '/comando', '/parar-tudo', '/rearmar', '/fila', '/config', '/faces', '/gestos', '/app', '/rtc', '/camera', '/conversa', '/treinamento', '/braco', '/servos', '/ia', '/api', '/gesto', '/face', - '/carinha.html', '/reacoes-render.js', '/rastreador-worker.js', '/vendor', '/qualidade-auto.js', '/app.apk']; + '/carinha.html', '/reacoes-render.js', '/rosto-motor.js', '/rastreador-worker.js', '/vendor', '/qualidade-auto.js', '/app.apk']; export default defineConfig({ plugins: [svelte()],