diff --git a/android/app/assets/carinha.html b/android/app/assets/carinha.html index 1bc7f57..37c1b08 100644 --- a/android/app/assets/carinha.html +++ b/android/app/assets/carinha.html @@ -98,6 +98,11 @@ const VERM = [255, 78, 78]; const ROSA = [255, 112, 176]; const AMARELO = [255, 218, 96]; const AZUL = [130, 170, 255]; +// Tons derivados da cor escolhida no painel (CIANO é trocada pela cor escolhida em tempo real): +// "claro" para susto/surpresa, "escuro" para tristeza e sono. Nada de azul fixo. +const corClara = (k) => CIANO.map((v) => v + (255 - v) * (k === undefined ? 0.4 : k)); +const corEscura = (k) => CIANO.map((v) => v * (k === undefined ? 0.62 : k)); +function resolverCor(c) { return c === "claro" ? corClara() : c === "escuro" ? corEscura() : c === "escolhida" ? CIANO.slice() : c; } const VERDE = [120, 255, 160]; const BRANCO = [245, 250, 255]; @@ -302,7 +307,7 @@ function sequencias() { const olhar_baixo = [[{ dy: 11 }, 0.16], [{}, 0.45], [{ dy: 0 }, 0.2]]; const feliz = [[{ forma: "feliz", esc: 1.05, boca: "sorriso" }, 0.16], [{ esc: 1.16 }, 0.18], [{ esc: 1.02 }, 0.16], [{ esc: 1.13 }, 0.16], [{ esc: 1.0 }, 0.2]]; - const surpreso = [[{ forma: "aberto", esc: 1.3, ab: 1.12, dy: -8, cor: CIANO_E, boca: "aberta" }, 0.09], + const surpreso = [[{ forma: "aberto", esc: 1.3, ab: 1.12, dy: -8, cor: "claro", boca: "aberta" }, 0.09], [{ dy: -10 }, 0.5], [{ esc: 1.0, ab: 1.0, dy: 0, cor: CIANO }, 0.25]]; const bravo = [[{ forma: "bravo", cor: VERM, esc: 0.98, boca: "brava" }, 0.1], @@ -311,7 +316,7 @@ function sequencias() { const coracao = [[{ forma: "coracao", cor: ROSA, boca: "sorriso" }, 0.12], [{ esc: 1.18 }, 0.15], [{ esc: 1.0 }, 0.15], [{ esc: 1.18 }, 0.15], [{ esc: 1.0 }, 0.15], [{ forma: "aberto", cor: CIANO }, 0.3]]; - const triste = [[{ forma: "triste", cor: AZUL, dy: 5, boca: "triste" }, 0.18], [{ dy: 7 }, 0.5], + const triste = [[{ forma: "triste", cor: "escuro", dy: 5, boca: "triste" }, 0.18], [{ dy: 7 }, 0.5], [{ forma: "aberto", cor: CIANO, dy: 0 }, 0.3]]; const piscadinha = [[{ forma2: "dormir", esc: 1.04, boca: "sorriso" }, 0.12], [{ esc: 1.08 }, 0.5], [{ forma2: "aberto", esc: 1.0 }, 0.18]]; @@ -344,6 +349,7 @@ function proximo() { const [alvo, dur] = r.fila[0]; r.kf_ini = { ab: r.ab, ab2: r.ab2, esc: r.esc, dx: r.dx, dy: r.dy }; r.cor_ini = r.cor.slice(); + if ("cor" in alvo) alvo.cor = resolverCor(alvo.cor); // "claro"/"escuro" viram tons da cor escolhida if ("forma" in alvo) r.forma = alvo.forma; if ("forma2" in alvo) r.forma2 = alvo.forma2; if ("boca" in alvo) r.boca = alvo.boca; @@ -378,7 +384,7 @@ function passo(dt) { // avanca a fila; true se ha gesto em function repouso(t) { // pose calma: olha devagar, "respira" if (r.dormindo) { r.forma = "dormir"; r.forma2 = "dormir"; r.boca = "sono"; - r.cor = lerpCor(AZUL, [40, 60, 120], 0.5 + 0.5 * Math.sin(t * 1.2)); + r.cor = lerpCor(corEscura(0.75), corEscura(0.35), 0.5 + 0.5 * Math.sin(t * 1.2)); // respira na cor escolhida r.ab = 0; r.ab2 = 0; r.esc = 1.0 + 0.03 * Math.sin(t * 1.4); r.dx = 0; @@ -536,7 +542,7 @@ function pose(nome) { for (const k of ["forma", "forma2", "boca", "esc", "dx", "dy", "ab", "ab2"]) { if (k in alvo && alvo[k] !== undefined) r[k] = alvo[k]; } - if ("cor" in alvo) r.cor = alvo.cor.slice(); + if ("cor" in alvo) r.cor = resolverCor(alvo.cor).slice(); congelado = true; desenhar(); return true; diff --git a/carinha.html b/carinha.html index 1bc7f57..37c1b08 100644 --- a/carinha.html +++ b/carinha.html @@ -98,6 +98,11 @@ const VERM = [255, 78, 78]; const ROSA = [255, 112, 176]; const AMARELO = [255, 218, 96]; const AZUL = [130, 170, 255]; +// Tons derivados da cor escolhida no painel (CIANO é trocada pela cor escolhida em tempo real): +// "claro" para susto/surpresa, "escuro" para tristeza e sono. Nada de azul fixo. +const corClara = (k) => CIANO.map((v) => v + (255 - v) * (k === undefined ? 0.4 : k)); +const corEscura = (k) => CIANO.map((v) => v * (k === undefined ? 0.62 : k)); +function resolverCor(c) { return c === "claro" ? corClara() : c === "escuro" ? corEscura() : c === "escolhida" ? CIANO.slice() : c; } const VERDE = [120, 255, 160]; const BRANCO = [245, 250, 255]; @@ -302,7 +307,7 @@ function sequencias() { const olhar_baixo = [[{ dy: 11 }, 0.16], [{}, 0.45], [{ dy: 0 }, 0.2]]; const feliz = [[{ forma: "feliz", esc: 1.05, boca: "sorriso" }, 0.16], [{ esc: 1.16 }, 0.18], [{ esc: 1.02 }, 0.16], [{ esc: 1.13 }, 0.16], [{ esc: 1.0 }, 0.2]]; - const surpreso = [[{ forma: "aberto", esc: 1.3, ab: 1.12, dy: -8, cor: CIANO_E, boca: "aberta" }, 0.09], + const surpreso = [[{ forma: "aberto", esc: 1.3, ab: 1.12, dy: -8, cor: "claro", boca: "aberta" }, 0.09], [{ dy: -10 }, 0.5], [{ esc: 1.0, ab: 1.0, dy: 0, cor: CIANO }, 0.25]]; const bravo = [[{ forma: "bravo", cor: VERM, esc: 0.98, boca: "brava" }, 0.1], @@ -311,7 +316,7 @@ function sequencias() { const coracao = [[{ forma: "coracao", cor: ROSA, boca: "sorriso" }, 0.12], [{ esc: 1.18 }, 0.15], [{ esc: 1.0 }, 0.15], [{ esc: 1.18 }, 0.15], [{ esc: 1.0 }, 0.15], [{ forma: "aberto", cor: CIANO }, 0.3]]; - const triste = [[{ forma: "triste", cor: AZUL, dy: 5, boca: "triste" }, 0.18], [{ dy: 7 }, 0.5], + const triste = [[{ forma: "triste", cor: "escuro", dy: 5, boca: "triste" }, 0.18], [{ dy: 7 }, 0.5], [{ forma: "aberto", cor: CIANO, dy: 0 }, 0.3]]; const piscadinha = [[{ forma2: "dormir", esc: 1.04, boca: "sorriso" }, 0.12], [{ esc: 1.08 }, 0.5], [{ forma2: "aberto", esc: 1.0 }, 0.18]]; @@ -344,6 +349,7 @@ function proximo() { const [alvo, dur] = r.fila[0]; r.kf_ini = { ab: r.ab, ab2: r.ab2, esc: r.esc, dx: r.dx, dy: r.dy }; r.cor_ini = r.cor.slice(); + if ("cor" in alvo) alvo.cor = resolverCor(alvo.cor); // "claro"/"escuro" viram tons da cor escolhida if ("forma" in alvo) r.forma = alvo.forma; if ("forma2" in alvo) r.forma2 = alvo.forma2; if ("boca" in alvo) r.boca = alvo.boca; @@ -378,7 +384,7 @@ function passo(dt) { // avanca a fila; true se ha gesto em function repouso(t) { // pose calma: olha devagar, "respira" if (r.dormindo) { r.forma = "dormir"; r.forma2 = "dormir"; r.boca = "sono"; - r.cor = lerpCor(AZUL, [40, 60, 120], 0.5 + 0.5 * Math.sin(t * 1.2)); + r.cor = lerpCor(corEscura(0.75), corEscura(0.35), 0.5 + 0.5 * Math.sin(t * 1.2)); // respira na cor escolhida r.ab = 0; r.ab2 = 0; r.esc = 1.0 + 0.03 * Math.sin(t * 1.4); r.dx = 0; @@ -536,7 +542,7 @@ function pose(nome) { for (const k of ["forma", "forma2", "boca", "esc", "dx", "dy", "ab", "ab2"]) { if (k in alvo && alvo[k] !== undefined) r[k] = alvo[k]; } - if ("cor" in alvo) r.cor = alvo.cor.slice(); + if ("cor" in alvo) r.cor = resolverCor(alvo.cor).slice(); congelado = true; desenhar(); return true; diff --git a/reacoes-render.js b/reacoes-render.js index 71c1add..b8516d0 100644 --- a/reacoes-render.js +++ b/reacoes-render.js @@ -1,4 +1,12 @@ (function(){ + // Cores das receitas: o ciano padrão (#5cd6ff) vira a cor escolhida no painel e o azul-claro + // (#aaccff) um tom mais claro dela; rosa, amarelo e verde continuam (fazem parte da emoção). + function corDaReacao(hex){ + const h=String(hex||'').toLowerCase(), base=(typeof CIANO!=='undefined'?CIANO:[92,214,255]); + if(h==='#5cd6ff')return base.slice(); + if(h==='#aaccff')return base.map(v=>v+(255-v)*.45); + return [1,3,5].map(i=>parseInt(h.slice(i,i+2),16)); + } const icons={nenhum:'',estrela:'✦',coracao:'♥',musica:'♫',cafe:'☕',ideia:'💡'}; const badge=document.createElement('div');badge.id='reacaoSimbolo';badge.style.cssText='position:fixed;left:5%;top:6%;z-index:15;color:#5cd6ff;font:clamp(30px,7vw,64px) sans-serif;pointer-events:none;white-space:pre-wrap';document.body.append(badge); let timer,last=null,fetching=false,animation;let particles=[]; @@ -42,7 +50,7 @@ for(const s of recipe.passos)if(!['aberto','feliz','surpreso','coracao','triste'].includes(s.olhos)||!['neutra','sorriso','aberta','triste'].includes(s.boca)||!/^#[0-9a-f]{6}$/i.test(s.cor)||!Number.isFinite(s.duracao)||s.duracao<.15||s.duracao>2||!Number.isFinite(s.dx)||Math.abs(s.dx)>25||!Number.isFinite(s.dy)||Math.abs(s.dy)>12||!Number.isFinite(s.escala)||s.escala<.8||s.escala>1.3)return; clearTimeout(timer);clearVisual();window.eilik.soltar();trata('acordar');MIC.ultimoSom=performance.now()/1000; visual(recipe); - r.fila=recipe.passos.map(s=>[{forma:s.olhos,forma2:null,boca:s.boca,cor:[1,3,5].map(i=>parseInt(s.cor.slice(i,i+2),16)),dx:s.dx,dy:s.dy,esc:s.escala,ab:1,ab2:1},s.duracao]); + r.fila=recipe.passos.map(s=>[{forma:s.olhos,forma2:null,boca:s.boca,cor:corDaReacao(s.cor),dx:s.dx,dy:s.dy,esc:s.escala,ab:1,ab2:1},s.duracao]); r.fila.push([{forma:'aberto',forma2:null,boca:'neutra',cor:CIANO.slice(),dx:0,dy:0,esc:1,ab:1,ab2:1},.4]);proximo(); timer=setTimeout(clearVisual,Math.max(recipe.figurinha?6000:0,['musica','estrela','coracao'].includes(recipe.simbolo)?4500:['ideia','cafe'].includes(recipe.simbolo)?2500:0,recipe.passos.reduce((n,s)=>n+s.duracao,0)*1000+400)); } diff --git a/web/src/lib/componentes/Miniatura.svelte b/web/src/lib/componentes/Miniatura.svelte index 16546e8..7a69f9e 100644 --- a/web/src/lib/componentes/Miniatura.svelte +++ b/web/src/lib/componentes/Miniatura.svelte @@ -25,6 +25,13 @@ if (['musica', 'estrela', 'coracao'].includes(receita?.simbolo)) return { emoji: SIMBOLO_EMOJI[receita.simbolo] }; return null; }); + // Mesma regra do celular (reacoes-render.js): ciano padrão = cor escolhida; azul-claro = tom claro dela. + function corDaReacao(hex: string | undefined): number[] { + const h = (hex ?? '').toLowerCase(), base = estado.aparencia.cor; + if (!/^#[0-9a-f]{6}$/.test(h) || h === '#5cd6ff') return [...base]; + if (h === '#aaccff') return base.map((v) => v + (255 - v) * 0.45); + return rgb(h); + } const estilo = $derived(ROSTOS_INFO[estado.aparencia.rosto]?.novo ? estado.aparencia.rosto : 'vivo'); $effect(() => { @@ -36,7 +43,7 @@ motor.retrato(tela, { estilo, formato: estado.aparencia.formato ?? 'padrao', - cor: /^#[0-9a-f]{6}$/i.test(passo?.cor ?? '') ? rgb(passo.cor) : estado.aparencia.cor, + cor: corDaReacao(passo?.cor), forma: passo?.olhos ?? 'aberto', icone: nosOlhos.icone, desenho: nosOlhos.desenho ? $state.snapshot(nosOlhos.desenho) : null,