primocode 10.13.0 → 10.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -12
- package/bin/primocode.js +148 -8
- package/lib/act.js +48 -1
- package/lib/catalogo.js +12 -1
- package/lib/config.js +1 -0
- package/lib/estudio/cota.js +150 -0
- package/lib/estudio/dados/projetos/clube-ad5.json +105 -0
- package/lib/estudio/dados/projetos/clube-ae-sem-memoria.json +107 -0
- package/lib/estudio/dados/projetos/clube-agent.json +120 -0
- package/lib/estudio/dados/projetos/clube-antes-e-agora.json +86 -0
- package/lib/estudio/dados/projetos/clube-apresentando-clube.json +110 -0
- package/lib/estudio/dados/projetos/clube-bluevisa.json +106 -0
- package/lib/estudio/dados/projetos/clube-caught-in-the-fire.json +127 -0
- package/lib/estudio/dados/projetos/clube-chat-cliente-satisfeito.json +98 -0
- package/lib/estudio/dados/projetos/clube-chatgpt-anuncios.json +120 -0
- package/lib/estudio/dados/projetos/clube-claude-dj.json +140 -0
- package/lib/estudio/dados/projetos/clube-claude-mcp.json +142 -0
- package/lib/estudio/dados/projetos/clube-cleanui.json +106 -0
- package/lib/estudio/dados/projetos/clube-clinica-take-unico.json +128 -0
- package/lib/estudio/dados/projetos/clube-clinica.json +104 -0
- package/lib/estudio/dados/projetos/clube-clube-opener.json +125 -0
- package/lib/estudio/dados/projetos/clube-clube.json +108 -0
- package/lib/estudio/dados/projetos/clube-codigo.json +101 -0
- package/lib/estudio/dados/projetos/clube-distilbook.json +104 -0
- package/lib/estudio/dados/projetos/clube-drive-upload.json +115 -0
- package/lib/estudio/dados/projetos/clube-dub.json +119 -0
- package/lib/estudio/dados/projetos/clube-enxovaly.json +105 -0
- package/lib/estudio/dados/projetos/clube-fecha7.json +118 -0
- package/lib/estudio/dados/projetos/clube-filatov.json +128 -0
- package/lib/estudio/dados/projetos/clube-frame.json +108 -0
- package/lib/estudio/dados/projetos/clube-glass.json +118 -0
- package/lib/estudio/dados/projetos/clube-letra-em-apps.json +84 -0
- package/lib/estudio/dados/projetos/clube-letra-globo-3d.json +111 -0
- package/lib/estudio/dados/projetos/clube-letra-nos-apps.json +146 -0
- package/lib/estudio/dados/projetos/clube-letra-seis-mundos.json +100 -0
- package/lib/estudio/dados/projetos/clube-lula-3.json +146 -0
- package/lib/estudio/dados/projetos/clube-morph.json +119 -0
- package/lib/estudio/dados/projetos/clube-motion-designer.json +115 -0
- package/lib/estudio/dados/projetos/clube-motion-pacote.json +112 -0
- package/lib/estudio/dados/projetos/clube-movimento.json +103 -0
- package/lib/estudio/dados/projetos/clube-not-like-us.json +117 -0
- package/lib/estudio/dados/projetos/clube-pinterest-inspiracao.json +86 -0
- package/lib/estudio/dados/projetos/clube-pixel-e-tinta.json +108 -0
- package/lib/estudio/dados/projetos/clube-ponte.json +118 -0
- package/lib/estudio/dados/projetos/clube-processo-edit-tonal.json +126 -0
- package/lib/estudio/dados/projetos/clube-processo-motion-100-ia.json +109 -0
- package/lib/estudio/dados/projetos/clube-promo.json +114 -0
- package/lib/estudio/dados/projetos/clube-proposito.json +115 -0
- package/lib/estudio/dados/projetos/clube-rankhog.json +128 -0
- package/lib/estudio/dados/projetos/clube-recursao.json +116 -0
- package/lib/estudio/dados/projetos/clube-revelar.json +118 -0
- package/lib/estudio/dados/projetos/clube-robo.json +125 -0
- package/lib/estudio/dados/projetos/clube-shelby-ep2.json +144 -0
- package/lib/estudio/dados/projetos/clube-shelby.json +97 -0
- package/lib/estudio/dados/projetos/clube-solar-eclipse.json +96 -0
- package/lib/estudio/dados/projetos/clube-soldier.json +128 -0
- package/lib/estudio/dados/projetos/clube-som-de-cena.json +108 -0
- package/lib/estudio/dados/projetos/clube-spotify-candidatura.json +112 -0
- package/lib/estudio/dados/projetos/clube-tda-app.json +118 -0
- package/lib/estudio/dados/projetos/clube-tda-ia.json +75 -0
- package/lib/estudio/dados/projetos/clube-telegram-chat.json +118 -0
- package/lib/estudio/dados/projetos/clube-telegram-ilha.json +106 -0
- package/lib/estudio/dados/projetos/clube-tennessee-nike.json +132 -0
- package/lib/estudio/dados/projetos/clube-tudo-se-move.json +112 -0
- package/lib/estudio/dados/projetos/clube-uiad.json +107 -0
- package/lib/estudio/dados/projetos/clube-viralgrow.json +108 -0
- package/lib/estudio/dados/projetos/clube-whose-side.json +140 -0
- package/lib/estudio/dados/projetos/clube-youtube-inscrever.json +108 -0
- package/lib/estudio/dados/projetos/elementos-do-site-em-movimento.json +49 -0
- package/lib/estudio/dados/projetos/explainer-narrado.json +51 -0
- package/lib/estudio/dados/projetos/lancamento-de-produto.json +51 -0
- package/lib/estudio/dados/projetos/motion-so-com-sons.json +50 -0
- package/lib/estudio/dados/projetos/titulo-em-after-effects.json +51 -0
- package/lib/estudio/dados/projetos/tour-de-saas.json +50 -0
- package/lib/estudio/dados/projetos-ae/antes-e-agora/ae/cenas.jsx +733 -0
- package/lib/estudio/dados/projetos-ae/antes-e-agora/assets/fazer_assets.py +88 -0
- package/lib/estudio/dados/projetos-ae/letra-em-apps/ae/cenas.jsx +402 -0
- package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/preparar_assets.py +17 -0
- package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/svg_para_ae.py +25 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/BRIEF-AGENTES.md +31 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/README.md +53 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ROTEIRO-CENAS.md +69 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/A-agenda.jsx +148 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/B-docs.jsx +174 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/C-alttab.jsx +113 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/D-spotify.jsx +118 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/E-notas.jsx +146 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/F-jornal1.jsx +144 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/G-google.jsx +153 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/H-mapa.jsx +176 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/I-imagens.jsx +132 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/J-jornal2.jsx +191 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/K-maps.jsx +184 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera-movimentos.jsx +48 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera.jsx +57 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/card-spotify.jsx +98 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/digitar.jsx +38 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/jornal-comum.jsx +196 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra.jsx +23 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra_automatica.py +83 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/montagem.jsx +74 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/render_html.py +13 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/util.jsx +162 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-midia-comum.jsx +114 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/wg-util.jsx +360 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/F-jornal1/render_html.py +13 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/render_w-midia.py +26 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/inclin.py +30 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_d.py +36 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_e.py +27 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ajustar_movimentos.py +61 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ancorar.py +74 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/assar.py +47 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/camera3d_jornal.py +172 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/comparar.py +32 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/dados_ae_jornal.py +46 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/folha_contato.py +28 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/homografia_jornal.py +74 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/integrar.py +44 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/medir_quadro_a_quadro.py +32 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/mesa_2d.py +64 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/plot_cenas.py +11 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/retificar_quadros.py +38 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/assar_ab.py +52 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/medir_ab.py +59 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ajustar_h.py +111 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_corrige_cam.py +17 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ecc_cadeia.py +80 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_finalizar_cam.py +65 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_mosaico.py +61 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/01-gramatica-e-roteiro.md +55 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/02-camera.md +66 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/03-montagem-no-ae.md +50 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/04-render-e-conferencia.md +43 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/05-abertura-celular-mergulho.md +43 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces.md +42 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/atraso_imagem.py +31 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/fundo.py +56 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/juntar.py +45 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/montar.py +177 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/rastreio.py +74 -0
- package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/sincronia.py +18 -0
- package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/ae/cenas.jsx +530 -0
- package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/assets/fazer_assets.py +107 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/assets/pessoas/figurinha.py +46 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/BRIEF-A.md +83 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/audio.py +179 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/confere.py +20 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte1.js +1 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte2.js +1 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/gerar_emojis.py +11 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/img/filmes/_indice.js +122 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/base.js +380 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/main.js +86 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1a.js +169 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1b.js +455 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1c.js +389 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p2.js +379 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/video.py +62 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/README.md +65 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/oraculo_take.py +137 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/render_take.py +388 -0
- package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/take.js +235 -0
- package/lib/estudio/editor.js +285 -0
- package/lib/estudio/effectcraft.js +152 -0
- package/lib/estudio/exportar.js +181 -0
- package/lib/estudio/index.js +90 -2
- package/lib/estudio/kit-ae/base.jsx +1146 -0
- package/lib/estudio/kit-ae/cenas.jsx +395 -0
- package/lib/estudio/kit-ae/primitivas.jsx +911 -0
- package/lib/estudio/maquina-diretor.js +393 -0
- package/lib/estudio/maquina-elementos.js +134 -0
- package/lib/estudio/maquina-layout.js +198 -0
- package/lib/estudio/maquina-som.js +478 -0
- package/lib/estudio/maquina-trilha.js +160 -0
- package/lib/estudio/maquina-voz.js +429 -0
- package/lib/estudio/maquina.js +516 -0
- package/lib/estudio/projetos.js +60 -0
- package/lib/headless.js +71 -0
- package/lib/hooks.js +72 -0
- package/lib/local/cerebro.json +398 -12
- package/lib/local/entrada.js +46 -2
- package/lib/marca-kit.js +309 -0
- package/lib/mcp.js +286 -6
- package/lib/perigo.js +31 -3
- package/lib/planos.js +47 -19
- package/lib/preparar.js +111 -0
- package/lib/retomar.js +55 -0
- package/lib/sandbox.js +197 -0
- package/lib/skills.js +3 -1
- package/lib/tools.js +13 -4
- package/lib/ui.js +1 -1
- package/package.json +4 -2
- package/skills/after-effects/SKILL.md +52 -0
- package/skills/maquina-de-motion/SKILL.md +84 -0
|
@@ -0,0 +1,1146 @@
|
|
|
1
|
+
/* base.jsx — o kit de motion do PrimoCode para o EffectCraft (ES3: só var e function).
|
|
2
|
+
|
|
3
|
+
Entra ANTES do script do modelo (concatenado pelo maquina.js; um `#include` também serve).
|
|
4
|
+
O modelo só chama funções de alto nível; as curvas, as molas e a câmera ficam aqui.
|
|
5
|
+
|
|
6
|
+
O MÉTODO vem dos projetos do Clube do Motion (curva por segmento, mola com quique, câmera em
|
|
7
|
+
cadeia de nulls, botão que afunda, palavra-chave em itálico, entrada por palavra), reescrito com
|
|
8
|
+
código nosso.
|
|
9
|
+
|
|
10
|
+
LIMITES DO EFFECTCRAFT 0.11.1 (medidos rodando o bin; o kit já contorna cada um):
|
|
11
|
+
1. `ADBE Text Selectors` nasce VAZIO e `.property('ADBE Text Range Advanced')` volta null: foi isso que
|
|
12
|
+
parou o antes-e-agora/cenas.jsx na linha 233 ("cannot convert null/undefined to object"). O
|
|
13
|
+
seletor existe só depois de `addProperty('ADBE Text Selector')`, e o grupo avançado se chama
|
|
14
|
+
'Advanced' (filhos 'basedOn', 'smoothness', ...). O kit usa isso, e a forma "rampa" do seletor
|
|
15
|
+
não existe (a entrada por letra usa Start animado, sem rampa).
|
|
16
|
+
2. Texto sem justificação explícita sai CENTRALIZADO na posição: o kit sempre define a justificação.
|
|
17
|
+
3. O nome da fonte casa por família nos .ttf de EFFECTCRAFT_FONT_DIRS ("Poppins", "Playfair Display"
|
|
18
|
+
com o arquivo 700i): não há `app.fonts`, nem lista de fontes, nem aviso quando a fonte falta.
|
|
19
|
+
4. 'ADBE Fast Blur' não existe; o desfoque é o 'ADBE Gaussian Blur 2'.
|
|
20
|
+
5. `trackMatteType` precisa de uma camada logo acima; o kit usa máscara (Mask Atom), que funciona.
|
|
21
|
+
6. A forma de máscara precisa de inTangents/outTangents explícitos (o kit os cria).
|
|
22
|
+
7. `app.fonts` e `File.exists` volta SEMPRE false (medido na 0.11.1, até com o arquivo ali): o Node confere os arquivos e o kit só tenta `importFile` dentro de try/catch.
|
|
23
|
+
8. O `writeLn` só chega ao Node na saída do script: o kit escreve uma linha "SOM {json}" por som
|
|
24
|
+
e "AVISO ..." por problema de layout (texto fora da tela).
|
|
25
|
+
|
|
26
|
+
Ordem de uso: novaComp -> fundo -> camera -> texto/forma/imagem/celular (parent = cam.no) -> som ->
|
|
27
|
+
fecha(comp). O maquina.js já faz isso por cena e junta as cenas com troca().
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
var KIT = { f: 1, entMax: 0, fps: 30, t0: 0, ajuste: 1, cams: {}, avisos: [], nSons: 0, marca: null, rects: [], voz: null, cenaIdx: 0, enq: 1, enqDy: 0, estilo: 'deriva', bpm: 0, elementos: [], ajusteCena: 1, MX: 0.08 };
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------- básicos
|
|
33
|
+
function kCor(h) {
|
|
34
|
+
if (h instanceof Array) return h;
|
|
35
|
+
h = String(h).replace('#', '');
|
|
36
|
+
if (h.length == 3) h = h.charAt(0) + h.charAt(0) + h.charAt(1) + h.charAt(1) + h.charAt(2) + h.charAt(2);
|
|
37
|
+
return [parseInt(h.substr(0, 2), 16) / 255, parseInt(h.substr(2, 2), 16) / 255, parseInt(h.substr(4, 2), 16) / 255];
|
|
38
|
+
}
|
|
39
|
+
function kLum(h) { var c = kCor(h); return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]; }
|
|
40
|
+
function kMisturar(a, b, p) { var x = kCor(a), y = kCor(b), r = []; for (var i = 0; i < 3; i++) r.push(x[i] + (y[i] - x[i]) * p); return r; }
|
|
41
|
+
function kTr(L) { return L.property('ADBE Transform Group'); }
|
|
42
|
+
function kP(L) { return kTr(L).property('ADBE Position'); }
|
|
43
|
+
function kS(L) { return kTr(L).property('ADBE Scale'); }
|
|
44
|
+
function kR(L) { return kTr(L).property('ADBE Rotate Z'); }
|
|
45
|
+
function kO(L) { return kTr(L).property('ADBE Opacity'); }
|
|
46
|
+
function kA(L) { return kTr(L).property('ADBE Anchor Point'); }
|
|
47
|
+
function kFx(L, mn) { return L.property('ADBE Effect Parade').addProperty(mn); }
|
|
48
|
+
function kN(prop) {
|
|
49
|
+
var t = prop.propertyValueType;
|
|
50
|
+
if (t == PropertyValueType.TwoD || t == PropertyValueType.TwoD_SPATIAL) return 2;
|
|
51
|
+
if (t == PropertyValueType.ThreeD || t == PropertyValueType.ThreeD_SPATIAL) return 3;
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
/* kPai(filho, pai): o EffectCraft COMPENSA escala e rotação do pai no parentesco (o filho de um pai a 78% ganha 128%).
|
|
55
|
+
Aqui o filho volta a 100% e 0°; a posição o chamador define depois. */
|
|
56
|
+
function kPai(L, p) { L.parent = p; kS(L).setValue([100, 100]); kR(L).setValue(0); }
|
|
57
|
+
function kFrame(t) { return Math.round(t * KIT.fps) / KIT.fps; }
|
|
58
|
+
|
|
59
|
+
function novaComp(nome, w, h, dur, fps) {
|
|
60
|
+
KIT.fps = fps || 30;
|
|
61
|
+
var c = app.project.items.addComp(nome, w, h, 1, dur, KIT.fps);
|
|
62
|
+
c.motionBlur = true;
|
|
63
|
+
// obturador curto (90°, sempre ≤ 180°) e amostras de sobra: o desfoque acompanha o movimento sem virar mancha nem código de barras
|
|
64
|
+
try { c.shutterAngle = 90; c.shutterPhase = -45; c.motionBlurSamplesPerFrame = 16; c.motionBlurAdaptiveSampleLimit = 128; } catch (e) { }
|
|
65
|
+
c.bgColor = [0, 0, 0];
|
|
66
|
+
return c;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fundo: cor lisa + gradiente que anda (Gradient Ramp com os pontos em órbita) + brilhos à deriva: o fundo nunca fica morto.
|
|
70
|
+
function fundo(comp, cor, o) {
|
|
71
|
+
o = o || {};
|
|
72
|
+
var s = comp.layers.addSolid(kCor(cor), 'fundo', comp.width, comp.height, 1);
|
|
73
|
+
var b = o.brilho, W = comp.width, H = comp.height, d = comp.duration, i;
|
|
74
|
+
if (b) {
|
|
75
|
+
try { // o gradiente se mexe: dois pontos giram em volta do centro e a cor de ponta é o brilho do tema
|
|
76
|
+
var rp = kFx(s, 'ADBE Ramp');
|
|
77
|
+
rp.property('ADBE Ramp-0002').setValue(kCor(cor));
|
|
78
|
+
rp.property('ADBE Ramp-0004').setValue(kMisturar(cor, b, 0.9));
|
|
79
|
+
rp.property('ADBE Ramp-0001').expression = '[' + (W / 2) + ' + Math.cos(time * 0.9) * ' + (W * 0.45) + ', ' + (H / 2) + ' + Math.sin(time * 0.7) * ' + (H * 0.45) + ']';
|
|
80
|
+
rp.property('ADBE Ramp-0003').expression = '[' + (W / 2) + ' - Math.cos(time * 0.9) * ' + (W * 0.55) + ', ' + (H / 2) + ' - Math.sin(time * 0.7) * ' + (H * 0.55) + ']';
|
|
81
|
+
rp.property('ADBE Ramp-0005').setValue(2);
|
|
82
|
+
} catch (e) { }
|
|
83
|
+
for (i = 0; i < 3; i++) {
|
|
84
|
+
var L = comp.layers.addShape(); L.name = 'brilho ' + i;
|
|
85
|
+
var g = L.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
86
|
+
var el = g.property('ADBE Vectors Group').addProperty('ADBE Vector Shape - Ellipse');
|
|
87
|
+
var raio = Math.max(W, H) * (i == 1 ? 0.5 : i == 2 ? 0.4 : 0.7);
|
|
88
|
+
el.property('ADBE Vector Ellipse Size').setValue([raio, raio]);
|
|
89
|
+
var f = g.property('ADBE Vectors Group').addProperty('ADBE Vector Graphic - Fill');
|
|
90
|
+
f.property('ADBE Vector Fill Color').setValue(kCor(b));
|
|
91
|
+
kO(L).setValue(i == 0 ? 38 : i == 1 ? 30 : 24);
|
|
92
|
+
var bl = kFx(L, 'ADBE Gaussian Blur 2'); bl.property('ADBE Gaussian Blur 2-0001').setValue(raio * 0.35);
|
|
93
|
+
var a0 = [W * (i == 1 ? 0.85 : i == 2 ? 0.5 : 0.1), H * (i == 1 ? 0.75 : i == 2 ? 0.15 : 0.2)], a1 = [W * (i == 1 ? 0.2 : i == 2 ? 0.9 : 0.8), H * (i == 1 ? 0.3 : i == 2 ? 0.85 : 0.7)];
|
|
94
|
+
curva(kP(L), [[0, a0, 30, 30], [d / 2, a1, 30, 30], [d, a0, 30, 30]]);
|
|
95
|
+
L.motionBlur = false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return s;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------- curvas e molas
|
|
102
|
+
/* curva(prop, chaves): chaves = [[t, valor, influenciaEntrada, influenciaSaida], ...].
|
|
103
|
+
TODA chave leva ease (padrão: sai rápida 28, chega macia 72 = "snap" de interface).
|
|
104
|
+
influência -1 = linear; 'a' = automática contínua (a velocidade nunca zera: câmera). */
|
|
105
|
+
function curva(prop, chaves) {
|
|
106
|
+
var i, k, e, n = kN(prop);
|
|
107
|
+
var cs = [];
|
|
108
|
+
for (i = 0; i < chaves.length; i++) {
|
|
109
|
+
var tk = kFrame(chaves[i][0]);
|
|
110
|
+
if (i > 0 && tk <= cs[i - 1][0] + 1e-6) tk = cs[i - 1][0] + 1 / KIT.fps; // duas chaves no mesmo quadro: a segunda vence e a primeira some (foi o bug do opacity 0 das trocas)
|
|
111
|
+
cs.push([tk].concat(chaves[i].slice(1)));
|
|
112
|
+
}
|
|
113
|
+
for (i = 0; i < cs.length; i++) prop.setValueAtTime(cs[i][0], cs[i][1]);
|
|
114
|
+
for (i = 0; i < cs.length; i++) {
|
|
115
|
+
k = prop.nearestKeyIndex(cs[i][0]);
|
|
116
|
+
var ei = cs[i].length > 2 && cs[i][2] != null ? cs[i][2] : 72;
|
|
117
|
+
var eo = cs[i].length > 3 && cs[i][3] != null ? cs[i][3] : 28;
|
|
118
|
+
if (ei === 'a' || eo === 'a') {
|
|
119
|
+
prop.setTemporalContinuousAtKey(k, true); prop.setTemporalAutoBezierAtKey(k, true);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
var ie = [], oe = [];
|
|
123
|
+
for (e = 0; e < n; e++) { ie.push(new KeyframeEase(0, Math.max(0.1, Math.min(100, ei < 0 ? 33 : ei)))); oe.push(new KeyframeEase(0, Math.max(0.1, Math.min(100, eo < 0 ? 33 : eo)))); }
|
|
124
|
+
prop.setTemporalEaseAtKey(k, ie, oe);
|
|
125
|
+
if (ei < 0 || eo < 0) prop.setInterpolationTypeAtKey(k, ei < 0 ? KeyframeInterpolationType.LINEAR : KeyframeInterpolationType.BEZIER, eo < 0 ? KeyframeInterpolationType.LINEAR : KeyframeInterpolationType.BEZIER);
|
|
126
|
+
if (prop.isSpatial && prop.matchName == 'ADBE Position') {
|
|
127
|
+
var z = (n == 3) ? [0, 0, 0] : [0, 0];
|
|
128
|
+
prop.setSpatialAutoBezierAtKey(k, false); prop.setSpatialContinuousAtKey(k, false);
|
|
129
|
+
prop.setSpatialTangentsAtKey(k, z, z);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* mola(prop, t, de, para, {quique, dur}): mola amortecida amostrada a cada quadro.
|
|
135
|
+
quique 0 = chega sem passar; 0.45 = passa uns 7% e assenta; 0.8 = elástico. */
|
|
136
|
+
function mola(prop, t, de, para, o) {
|
|
137
|
+
o = o || {};
|
|
138
|
+
var q = o.quique != null ? o.quique : 0.45, dur = o.dur || 0.7;
|
|
139
|
+
var z = Math.max(0.28, 0.95 - 0.7 * q), wn = 3.9 / (z * dur);
|
|
140
|
+
var wd = wn * Math.sqrt(Math.max(0.0001, 1 - z * z));
|
|
141
|
+
var arr = (de instanceof Array), n = arr ? de.length : 1, passos = Math.max(3, Math.round(dur * KIT.fps)), i, j;
|
|
142
|
+
for (i = 0; i <= passos; i++) {
|
|
143
|
+
var tau = dur * i / passos, p;
|
|
144
|
+
if (i == passos) p = 1;
|
|
145
|
+
else p = 1 - Math.exp(-z * wn * tau) * (Math.cos(wd * tau) + (z * wn / wd) * Math.sin(wd * tau));
|
|
146
|
+
var v;
|
|
147
|
+
if (arr) { v = []; for (j = 0; j < n; j++) v.push(de[j] + (para[j] - de[j]) * p); }
|
|
148
|
+
else v = de + (para - de) * p;
|
|
149
|
+
prop.setValueAtTime(kFrame(t) + tau, v);
|
|
150
|
+
}
|
|
151
|
+
return kFrame(t) + dur;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ---------------------------------------------------------------- sons
|
|
155
|
+
/* som(t, tipo, ganho): registra um evento de som. O Node lê as linhas "SOM {json}" e põe o efeito no tempo. */
|
|
156
|
+
function som(t, tipo, ganho) {
|
|
157
|
+
KIT.nSons++;
|
|
158
|
+
writeLn('SOM ' + JSON.stringify({ t: Math.round((KIT.t0 + t / (KIT.f || 1)) * 1000) / 1000, tipo: tipo, ganho: ganho == null ? 1 : ganho }));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ---------------------------------------------------------------- câmera
|
|
162
|
+
/* camera(comp): um null pai de tudo. O mundo tem as coordenadas do quadro; a câmera mira (âncora) e dá
|
|
163
|
+
zoom (escala). Nunca para: sempre há um zoom lento, e as chaves usam curva automática contínua.
|
|
164
|
+
cam.empurra(t, dx, dy, zoom): em t a câmera chega a (centro + dx, dy) com zoom (1 = quadro). */
|
|
165
|
+
function camera(comp) {
|
|
166
|
+
var no = comp.layers.addNull(comp.duration); no.name = 'CAM'; no.enabled = false;
|
|
167
|
+
var cx = comp.width / 2, cy = comp.height / 2;
|
|
168
|
+
kA(no).setValue([cx, cy]); kP(no).setValue([cx, cy - KIT.enqDy]);
|
|
169
|
+
var cam = { no: no, comp: comp, chaves: [], cx: cx, cy: cy, aplicado: false, estilo: KIT.estilo };
|
|
170
|
+
cam.empurra = function (t, dx, dy, zoom) { cam.chaves.push([t, dx || 0, dy || 0, zoom || 1]); return cam; };
|
|
171
|
+
KIT.cams[comp.name] = cam;
|
|
172
|
+
return cam;
|
|
173
|
+
}
|
|
174
|
+
function kAplicaCamera(cam) {
|
|
175
|
+
if (cam.aplicado) return; cam.aplicado = true;
|
|
176
|
+
var d = cam.comp.duration, ch = cam.chaves.slice(0);
|
|
177
|
+
ch.sort(function (a, b) { return a[0] - b[0]; });
|
|
178
|
+
var z0 = 1, z1 = ch.length ? Math.max(1.02, ch[ch.length - 1][3] + 0.04) : 1.06;
|
|
179
|
+
var lista = [[0, ch.length && ch[0][0] < 0.05 ? ch[0][1] : 0, ch.length && ch[0][0] < 0.05 ? ch[0][2] : 0, z0]];
|
|
180
|
+
var i;
|
|
181
|
+
for (i = 0; i < ch.length; i++) if (ch[i][0] >= 0.05) lista.push(ch[i]);
|
|
182
|
+
var u = lista[lista.length - 1];
|
|
183
|
+
if (u[0] < d - 0.05) lista.push([d, u[1] * 1.04, u[2] * 1.04 + 8, z1]);
|
|
184
|
+
var ka = [], ks = [];
|
|
185
|
+
for (i = 0; i < lista.length; i++) {
|
|
186
|
+
ka.push([lista[i][0], [cam.cx + lista[i][1] * 0.5, cam.cy + lista[i][2] * 0.5], 'a', 'a']);
|
|
187
|
+
var zc = Math.min(lista[i][3], 1.05); // o zoom das chaves é limitado: o conteúdo precisa continuar na área segura com a câmera perto
|
|
188
|
+
ks.push([lista[i][0], [zc * 100 * KIT.enq, zc * 100 * KIT.enq], 'a', 'a']);
|
|
189
|
+
}
|
|
190
|
+
curva(kA(cam.camNo || cam.no), ka); curva(kS(cam.camNo || cam.no), ks);
|
|
191
|
+
kEstiloCamera(cam, d);
|
|
192
|
+
}
|
|
193
|
+
/* Os estilos de câmera: cada um é uma expressão por cima das chaves (a câmera nunca para), sempre SUAVE e com ease: nada de tremor,
|
|
194
|
+
nada de corte seco de enquadramento (Joel, 18/10: "a tremedeira é horrível").
|
|
195
|
+
deriva (zoom lento) · pulso (respira na batida) · trilho (travelling lateral) · orbita (balanço de eixo suave)
|
|
196
|
+
· push (aproximação dramática) · chicote (chega varrendo, com ease) · cinema (eixo levemente torto + subida)
|
|
197
|
+
POR CIMA de qualquer estilo, a câmera RESPIRA: um push-in/out suave (+3,5% com ease cosseno) a cada ~1 s (ou a cada 1–2 batidas da
|
|
198
|
+
trilha) e, no começo da cena, um "speed ramp" (12% mais perto, fechando em 0,5 s com ease). */
|
|
199
|
+
function kPunchTimes(d) { // só o período (e a fase) da respiração; o instante é REAL, a cena roda em tempo nominal (×f)
|
|
200
|
+
var out = [], passo, tl, f = KIT.f || 1, dr = d / f;
|
|
201
|
+
if (KIT.bpm > 40) {
|
|
202
|
+
var bp = 60 / KIT.bpm; passo = bp < 0.45 ? bp * 2 : bp;
|
|
203
|
+
var off = (((KIT.t0 - (KIT.batidaFase || 0)) % passo) + passo) % passo; tl = passo - off; if (tl < 0.45) tl += passo;
|
|
204
|
+
} else { passo = 0.95; tl = 0.8; }
|
|
205
|
+
KIT.passoRespira = passo;
|
|
206
|
+
while (tl < dr - 0.35) { out.push(Math.round(tl * f * 1000) / 1000); tl += passo; }
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
function kPunchCodigo(P) { // mantido para as expressões da atmosfera: pe/pf agora são suaves (sem estouro): variam pouco, com ease
|
|
210
|
+
return 'var P = [' + P.join(',') + ']; var cur = -1; for (var i = 0; i < P.length; i++) { if (time >= P[i]) cur = i; } var tt = cur >= 0 ? time - P[cur] : 9; var pe = 0; var pf = 0; var sg = 1; ';
|
|
211
|
+
}
|
|
212
|
+
function kEstiloCamera(cam, d) {
|
|
213
|
+
var st = cam.estilo || 'deriva', u = Math.min(cam.comp.width, cam.comp.height) / 1080, W = cam.comp.width, f = KIT.f || 1;
|
|
214
|
+
var cn = cam.camNo || cam.no, A = kA(cn), S = kS(cn), R = kR(cn);
|
|
215
|
+
var P = kPunchTimes(d); KIT.punch = P;
|
|
216
|
+
var per = (KIT.passoRespira || 0.95), U = u.toFixed(3);
|
|
217
|
+
var fase = (KIT.bpm > 40 ? (KIT.t0 - (KIT.batidaFase || 0)) : KIT.t0);
|
|
218
|
+
var mult = '1', dx = '0', dy = '0', rot = '0';
|
|
219
|
+
if (st == 'pulso') { var bp = (KIT.bpm > 40 ? 60 / KIT.bpm : 0.5) * f; mult = '(1 + 0.02 * (0.5 - 0.5 * Math.cos(2 * Math.PI * (time % ' + bp.toFixed(4) + ') / ' + bp.toFixed(4) + ')))'; }
|
|
220
|
+
else if (st == 'trilho') { dx = '(time / ' + d.toFixed(3) + ' - 0.5) * ' + (W * 0.07).toFixed(1); mult = '1.05'; }
|
|
221
|
+
else if (st == 'orbita') { rot = 'Math.sin(time * 0.9 / ' + f + ') * 1.8'; mult = '1.05'; }
|
|
222
|
+
else if (st == 'push') { mult = '(1 + 0.06 * Math.pow(Math.min(1, time / ' + d.toFixed(3) + '), 1.6))'; rot = '-0.8 * Math.min(1, time / ' + d.toFixed(3) + ')'; }
|
|
223
|
+
else if (st == 'chicote') { dx = '(1 - Math.pow(Math.min(1, time / ' + (0.5 * f).toFixed(3) + '), 0.4)) * ' + (W * 0.08).toFixed(1); }
|
|
224
|
+
else if (st == 'cinema') { rot = '-1.4 + Math.sin(time * 0.6 / ' + f + ') * 0.4'; dy = '-Math.min(1, time / ' + d.toFixed(3) + ') * ' + (28 * u).toFixed(1); }
|
|
225
|
+
var ease = 'var e = Math.min(1, time / ' + (0.5 * f).toFixed(3) + '); e = e * e * (3 - 2 * e); ';
|
|
226
|
+
var ramp = '(1 + 0.12 * (1 - e))';
|
|
227
|
+
var resp = '(1 + 0.035 * (0.5 - 0.5 * Math.cos(2 * Math.PI * ((time / ' + f + ' + ' + fase.toFixed(3) + ') % ' + per.toFixed(3) + ') / ' + per.toFixed(3) + ')))';
|
|
228
|
+
S.expression = 'var s = value; ' + ease + 'var k = ' + mult + ' * ' + resp + ' * ' + ramp + '; [s[0] * k, s[1] * k]';
|
|
229
|
+
A.expression = 'value + [' + dx + ', ' + dy + ']';
|
|
230
|
+
R.expression = rot;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------------------------------------------------------------- atmosfera: luz, flash, brilho, aberração, grão
|
|
234
|
+
/* kAtmosfera(comp, pal): NO MÁXIMO 3 efeitos visuais ao mesmo tempo (hoje 2), e NUNCA flash branco (Joel, 18/10):
|
|
235
|
+
1) Glow (brilho do que é claro), 2) um vazamento de luz suave (a aberração cromática VR foi tirada: deixava uma faixa de 1–2% na borda direita e na base) (mancha de cor
|
|
236
|
+
borrada em ADD, varrendo o quadro). A energia vem do movimento e da câmera, não de entulho. */
|
|
237
|
+
function kAtmosfera(comp, P) {
|
|
238
|
+
if (KIT.fx === false) return;
|
|
239
|
+
var W = comp.width, H = comp.height, u = Math.min(W, H) / 1080, pun = KIT.punch || [], cod = kPunchCodigo(pun), d = comp.duration;
|
|
240
|
+
try { // 3) vazamento de luz: uma mancha, sem pulso
|
|
241
|
+
var lk = comp.layers.addShape(); lk.name = 'vazamento de luz';
|
|
242
|
+
var gg = lk.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
243
|
+
var rr = Math.max(W, H) * 0.8;
|
|
244
|
+
gg.property('ADBE Vectors Group').addProperty('ADBE Vector Shape - Ellipse').property('ADBE Vector Ellipse Size').setValue([rr, rr * 0.7]);
|
|
245
|
+
gg.property('ADBE Vectors Group').addProperty('ADBE Vector Graphic - Fill').property('ADBE Vector Fill Color').setValue(kCor(P.ac));
|
|
246
|
+
kFx(lk, 'ADBE Gaussian Blur 2').property('ADBE Gaussian Blur 2-0001').setValue(rr * 0.3);
|
|
247
|
+
lk.blendingMode = BlendingMode.ADD;
|
|
248
|
+
lk.motionBlur = false;
|
|
249
|
+
kP(lk).expression = '[' + (-W * 0.2) + ' + (time / ' + d.toFixed(2) + ') * ' + (W * 1.4) + ', ' + (H * 0.3).toFixed(0) + ' + Math.sin(time * 1.1) * ' + (H * 0.18).toFixed(0) + ']';
|
|
250
|
+
kO(lk).setValue(20);
|
|
251
|
+
} catch (e) { KIT.avisos.push('vazamento de luz indisponível'); }
|
|
252
|
+
try { // 1) e 2): a camada de ajuste
|
|
253
|
+
var aj = comp.layers.addSolid([1, 1, 1], 'look', W, H, 1);
|
|
254
|
+
aj.adjustmentLayer = true;
|
|
255
|
+
var gl = kFx(aj, 'ADBE Glo2');
|
|
256
|
+
gl.property('ADBE Glo2-0002').setValue(165); gl.property('ADBE Glo2-0003').setValue(40 * u);
|
|
257
|
+
gl.property('ADBE Glo2-0004').setValue(0.8);
|
|
258
|
+
} catch (e) { KIT.avisos.push('camada de look indisponível: ' + e); }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* O título é SEMPRE a camada de cima da cena (nada atravessa a caixa dele): as palavras vão para o topo da pilha. */
|
|
262
|
+
function kTituloPorCima() {
|
|
263
|
+
var i, T = KIT.titulosL || [];
|
|
264
|
+
for (i = T.length - 1; i >= 0; i--) { try { T[i].moveToBeginning(); } catch (e) { } }
|
|
265
|
+
KIT.titulosL = [];
|
|
266
|
+
}
|
|
267
|
+
// fecha(comp): aplica a câmera da comp, a atmosfera (luz, flash, look) e confere o layout. Chame uma vez, depois de montar a cena.
|
|
268
|
+
function fecha(comp) { var c = KIT.cams[comp.name]; kTituloPorCima(); kAjustaConteudo(comp, c); if (KIT.ambienteFn) KIT.ambienteFn(comp, c); if (c) kAplicaCamera(c); kAtmosfera(comp, KIT.pal || { ac: '#FFFFFF' }); kConfereCena(comp); kAuditoria(comp); }
|
|
269
|
+
|
|
270
|
+
// ---------------------------------------------------------------- formas
|
|
271
|
+
function kMascaraRect(L, x0, y0, x1, y1, r) {
|
|
272
|
+
var m = L.property('ADBE Mask Parade').addProperty('ADBE Mask Atom');
|
|
273
|
+
m.property('ADBE Mask Shape').setValue(kRetShape(x0, y0, x1, y1, r || 0));
|
|
274
|
+
return m.property('ADBE Mask Shape');
|
|
275
|
+
}
|
|
276
|
+
function kRetShape(x0, y0, x1, y1, r) {
|
|
277
|
+
var S = new Shape(), k = 0.5523;
|
|
278
|
+
r = Math.max(0, Math.min(r, (x1 - x0) / 2, (y1 - y0) / 2));
|
|
279
|
+
if (r < 0.5) {
|
|
280
|
+
S.vertices = [[x0, y0], [x1, y0], [x1, y1], [x0, y1]];
|
|
281
|
+
S.inTangents = [[0, 0], [0, 0], [0, 0], [0, 0]]; S.outTangents = [[0, 0], [0, 0], [0, 0], [0, 0]];
|
|
282
|
+
} else {
|
|
283
|
+
var c = r * (1 - k);
|
|
284
|
+
S.vertices = [[x0 + r, y0], [x1 - r, y0], [x1, y0 + r], [x1, y1 - r], [x1 - r, y1], [x0 + r, y1], [x0, y1 - r], [x0, y0 + r]];
|
|
285
|
+
S.inTangents = [[0, 0], [-r * k, 0], [0, 0], [0, -r * k], [0, 0], [r * k, 0], [0, 0], [0, r * k]];
|
|
286
|
+
S.outTangents = [[r * k, 0], [0, 0], [0, r * k], [0, 0], [-r * k, 0], [0, 0], [0, -r * k], [0, 0]];
|
|
287
|
+
}
|
|
288
|
+
S.closed = true;
|
|
289
|
+
return S;
|
|
290
|
+
}
|
|
291
|
+
function kCircShape(cx, cy, r) {
|
|
292
|
+
var S = new Shape(), k = 0.5523 * r;
|
|
293
|
+
S.vertices = [[cx, cy - r], [cx + r, cy], [cx, cy + r], [cx - r, cy]];
|
|
294
|
+
S.inTangents = [[-k, 0], [0, -k], [k, 0], [0, k]];
|
|
295
|
+
S.outTangents = [[k, 0], [0, k], [-k, 0], [0, -k]];
|
|
296
|
+
S.closed = true;
|
|
297
|
+
return S;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* entrada: 'pop' (estala com quique forte e balança) · 'sobe' (sobe do chão com mola) · 'fade' · 'cresce' · 'flip' (vira em 3D) · null.
|
|
301
|
+
Toda entrada é EXAGERADA de propósito (motion é extravagante): a escala vai a ~125% e assenta; depois a camada respira. */
|
|
302
|
+
function kRespira(L, fase) {
|
|
303
|
+
try {
|
|
304
|
+
var ph = (fase == null ? (KIT.nResp = (KIT.nResp || 0) + 1) * 1.37 : fase).toFixed(2);
|
|
305
|
+
kS(L).expression = 'var s = value; var k = 1 + 0.016 * Math.sin(time * 2.4 + ' + ph + '); [s[0] * k, s[1] * k]';
|
|
306
|
+
} catch (e) { }
|
|
307
|
+
}
|
|
308
|
+
function kMarcaEntrada(t) { if (t > KIT.entMax) KIT.entMax = t; }
|
|
309
|
+
function kEntrada(L, t, tipo, quique) {
|
|
310
|
+
if (!tipo) return;
|
|
311
|
+
kMarcaEntrada(t);
|
|
312
|
+
var esc = kS(L).value, p = kP(L).value, rot0 = kR(L).value;
|
|
313
|
+
if (tipo == 'pop') {
|
|
314
|
+
mola(kS(L), t, [0, 0], [esc[0], esc[1]], { quique: quique != null ? Math.max(quique, 0.78) : 0.85, dur: 0.7 });
|
|
315
|
+
if (rot0 == 0) mola(kR(L), t, ((KIT.nResp = (KIT.nResp || 0) + 1) % 2 ? 1 : -1) * 11, 0, { quique: 0.7, dur: 0.7 });
|
|
316
|
+
curva(kO(L), [[t, 0, null, 30], [t + 0.06, 100, 60, null]]);
|
|
317
|
+
kRespira(L);
|
|
318
|
+
} else if (tipo == 'sobe') {
|
|
319
|
+
mola(kP(L), t, [p[0], p[1] + 130], [p[0], p[1]], { quique: 0.72, dur: 0.7 });
|
|
320
|
+
curva(kO(L), [[t, 0, null, 30], [t + 0.18, 100, 60, null]]);
|
|
321
|
+
} else if (tipo == 'cresce') {
|
|
322
|
+
mola(kS(L), t, [esc[0] * 0.45, esc[1] * 0.45], [esc[0], esc[1]], { quique: 0.78, dur: 0.7 });
|
|
323
|
+
curva(kO(L), [[t, 0, null, 30], [t + 0.12, 100, 60, null]]);
|
|
324
|
+
kRespira(L);
|
|
325
|
+
} else if (tipo == 'fade') {
|
|
326
|
+
curva(kO(L), [[t, 0, null, 30], [t + 0.35, 100, 60, null]]);
|
|
327
|
+
} else if (tipo == 'flip') { // cartão que vira em 3D, com quique
|
|
328
|
+
L.threeDLayer = true;
|
|
329
|
+
var rx = L.property('ADBE Transform Group').property('ADBE Rotate X');
|
|
330
|
+
mola(rx, t, -95, 0, { quique: 0.7, dur: 0.8 });
|
|
331
|
+
curva(kO(L), [[t, 0, null, 30], [t + 0.1, 100, 60, null]]);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* forma(comp, 'circulo'|'retangulo'|'pilula', {x,y,w,h,r,cor,traco,tracoL,alfa,parent,t0,entrada,quique,nome}) */
|
|
336
|
+
function forma(comp, tipo, o) {
|
|
337
|
+
o = o || {};
|
|
338
|
+
var L = comp.layers.addShape(); L.name = o.nome || tipo;
|
|
339
|
+
if (o.parent) kPai(L, o.parent);
|
|
340
|
+
var g = L.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
341
|
+
var v = g.property('ADBE Vectors Group');
|
|
342
|
+
var w = o.w || 200, h = o.h || (tipo == 'circulo' ? w : 100);
|
|
343
|
+
if (tipo == 'circulo') {
|
|
344
|
+
v.addProperty('ADBE Vector Shape - Ellipse').property('ADBE Vector Ellipse Size').setValue([w, w]);
|
|
345
|
+
} else {
|
|
346
|
+
var rc = v.addProperty('ADBE Vector Shape - Rect');
|
|
347
|
+
rc.property('ADBE Vector Rect Size').setValue([w, h]);
|
|
348
|
+
rc.property('ADBE Vector Rect Roundness').setValue(tipo == 'pilula' ? Math.min(w, h) / 2 : (o.r || 0));
|
|
349
|
+
}
|
|
350
|
+
if (o.cor) v.addProperty('ADBE Vector Graphic - Fill').property('ADBE Vector Fill Color').setValue(kCor(o.cor));
|
|
351
|
+
if (o.traco) {
|
|
352
|
+
var st = v.addProperty('ADBE Vector Graphic - Stroke');
|
|
353
|
+
st.property('ADBE Vector Stroke Color').setValue(kCor(o.traco));
|
|
354
|
+
st.property('ADBE Vector Stroke Width').setValue(o.tracoL || 4);
|
|
355
|
+
}
|
|
356
|
+
kP(L).setValue([o.x == null ? comp.width / 2 : o.x, o.y == null ? comp.height / 2 : o.y]);
|
|
357
|
+
if (o.alfa != null) kO(L).setValue(o.alfa);
|
|
358
|
+
if (o.esc) kS(L).setValue([o.esc, o.esc]);
|
|
359
|
+
if (o.entrada) kEntrada(L, o.t0 || 0, o.entrada, o.quique);
|
|
360
|
+
return L;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// o V de "feito": um traço aberto com ponta redonda, desenhado por trim
|
|
364
|
+
function check(comp, o) {
|
|
365
|
+
o = o || {};
|
|
366
|
+
var L = comp.layers.addShape(); L.name = o.nome || 'check';
|
|
367
|
+
if (o.parent) kPai(L, o.parent);
|
|
368
|
+
var g = L.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
369
|
+
var v = g.property('ADBE Vectors Group');
|
|
370
|
+
var tam = o.tam || 40;
|
|
371
|
+
var pa = v.addProperty('ADBE Vector Shape - Group');
|
|
372
|
+
var S = new Shape(); S.vertices = [[-0.42 * tam, 0.02 * tam], [-0.1 * tam, 0.34 * tam], [0.44 * tam, -0.32 * tam]];
|
|
373
|
+
S.inTangents = [[0, 0], [0, 0], [0, 0]]; S.outTangents = [[0, 0], [0, 0], [0, 0]]; S.closed = false;
|
|
374
|
+
pa.property('ADBE Vector Shape').setValue(S);
|
|
375
|
+
var st = v.addProperty('ADBE Vector Graphic - Stroke');
|
|
376
|
+
st.property('ADBE Vector Stroke Color').setValue(kCor(o.cor || '#FFFFFF'));
|
|
377
|
+
st.property('ADBE Vector Stroke Width').setValue(o.espessura || tam * 0.2);
|
|
378
|
+
try { st.property('ADBE Vector Stroke Line Cap').setValue(2); st.property('ADBE Vector Stroke Line Join').setValue(2); } catch (e) { }
|
|
379
|
+
kP(L).setValue([o.x || 0, o.y || 0]);
|
|
380
|
+
if (o.t0 != null) {
|
|
381
|
+
var tm = v.addProperty('ADBE Vector Filter - Trim');
|
|
382
|
+
curva(tm.property('ADBE Vector Trim End'), [[o.t0, 0, null, 25], [o.t0 + 0.28, 100, 75, null]]);
|
|
383
|
+
}
|
|
384
|
+
return L;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ---------------------------------------------------------------- texto
|
|
388
|
+
function kMedir(comp, s, fonte, tam, trk) {
|
|
389
|
+
var L = comp.layers.addText(s);
|
|
390
|
+
kDoc(L, fonte, tam, [1, 1, 1], { tracking: trk || 0 });
|
|
391
|
+
var w = L.sourceRectAtTime(0, false).width;
|
|
392
|
+
L.remove();
|
|
393
|
+
return w;
|
|
394
|
+
}
|
|
395
|
+
function kDoc(L, fonte, tam, cor, extra) {
|
|
396
|
+
var td = L.property('ADBE Text Properties').property('ADBE Text Document');
|
|
397
|
+
var d = td.value;
|
|
398
|
+
d.resetCharStyle();
|
|
399
|
+
d.font = fonte; d.fontSize = tam; d.applyFill = true; d.fillColor = kCor(cor); d.applyStroke = false;
|
|
400
|
+
d.justification = (extra && extra.just == 'left') ? ParagraphJustification.LEFT_JUSTIFY : ParagraphJustification.CENTER_JUSTIFY;
|
|
401
|
+
if (extra && extra.tracking != null) d.tracking = extra.tracking;
|
|
402
|
+
td.setValue(d);
|
|
403
|
+
return td;
|
|
404
|
+
}
|
|
405
|
+
function kPalavras(s) {
|
|
406
|
+
// *palavra* marca a palavra-chave; devolve [{t:'texto', kw:true|false}]
|
|
407
|
+
var p = String(s).replace(/\s+/g, ' ').split(' '), r = [], i;
|
|
408
|
+
for (i = 0; i < p.length; i++) {
|
|
409
|
+
if (!p[i]) continue;
|
|
410
|
+
var kw = false, t = p[i];
|
|
411
|
+
if (t.charAt(0) == '*' ) { kw = true; t = t.replace(/\*/g, ''); }
|
|
412
|
+
else if (t.indexOf('*') >= 0) { t = t.replace(/\*/g, ''); }
|
|
413
|
+
r.push({ t: t, kw: kw });
|
|
414
|
+
}
|
|
415
|
+
return r;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* texto(comp, str, {fonte, fonteDestaque, tamanho, cor, corDestaque, x, y, largura, maxLinhas, peso, entrada, t0, parent, passo, livre, sobrepoe, fala})
|
|
419
|
+
entrada: 'palavra' | 'letra' | 'sobe' | 'mascara'. A palavra entre *asteriscos* é a palavra-chave; o REALCE vem do
|
|
420
|
+
sistema tipográfico do vídeo (KIT.tipo.realce): 'italico' (itálico + cor + sublinhado) · 'caixa' (marca-texto atrás) ·
|
|
421
|
+
'cor' (só a cor) · 'sublinha' (sublinhado sem trocar a fonte). Cada palavra é uma camada: o kit mede com
|
|
422
|
+
sourceRectAtTime, quebra as linhas, encolhe o corpo até caber e ENCAIXA o bloco na área segura (parent = câmera).
|
|
423
|
+
Com narração (KIT.voz), cada palavra entra NO INSTANTE em que é dita ("nada aparece antes de ser dito").
|
|
424
|
+
Devolve {camadas, w, h, fim, tam, linhas}. */
|
|
425
|
+
function kNorm(s) {
|
|
426
|
+
s = String(s).toLowerCase();
|
|
427
|
+
var de = 'áàâãäéèêëíìîïóòôõöúùûüçñ', pa = 'aaaaaeeeeiiiiooooouuuucn', i;
|
|
428
|
+
for (i = 0; i < de.length; i++) s = s.split(de.charAt(i)).join(pa.charAt(i));
|
|
429
|
+
return s.replace(/[^a-z0-9]/g, '');
|
|
430
|
+
}
|
|
431
|
+
// o tempo (local da cena) em que a palavra é dita; null se não há voz ou a palavra não foi dita nesta cena
|
|
432
|
+
function kFalaBusca(w) {
|
|
433
|
+
if (!KIT.voz) return null;
|
|
434
|
+
var n = kNorm(w), P = KIT.voz.palavras, i;
|
|
435
|
+
if (n.length < 2) return null;
|
|
436
|
+
for (i = 0; i < P.length; i++) {
|
|
437
|
+
if (P[i].cena != KIT.cenaIdx) continue;
|
|
438
|
+
var pn = P[i].n || kNorm(P[i].w);
|
|
439
|
+
if (pn == n || (n.length >= 5 && pn.length >= 5 && pn.substr(0, 5) == n.substr(0, 5))) return Math.max(0.05, P[i].t - KIT.t0);
|
|
440
|
+
}
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
/* Q(trecho, padrao): o instante local em que o trecho é dito (a 1ª palavra que casa); sem voz, o padrão. */
|
|
444
|
+
function Q(trecho, padrao) {
|
|
445
|
+
if (!KIT.voz) return padrao;
|
|
446
|
+
var ps = String(trecho).replace(/\*/g, '').split(' '), i, melhor = null;
|
|
447
|
+
for (i = 0; i < ps.length; i++) { var t = kFalaBusca(ps[i]); if (t != null && (ps[i].length >= 3 || melhor == null)) { melhor = t; if (ps[i].length >= 3) break; } }
|
|
448
|
+
return melhor != null ? melhor : Math.max(padrao, 0.25);
|
|
449
|
+
}
|
|
450
|
+
/* A zona segura vem em coordenadas do MUNDO (o que o espectador vê) e é traduzida para as do LAYOUT (antes da câmera), que o kit usa para
|
|
451
|
+
posicionar: mundo = (cy − subida) + (y − cy) × enq × zoom, com zoom ≤ 1,08 (respiração × estilo). Assim o que está dentro da zona no layout
|
|
452
|
+
continua dentro dela com a câmera perto. 9:16: texto fora das faixas de UI do Reels (14% em cima, 20% embaixo; com legenda, 27%). */
|
|
453
|
+
function kParaLayout(comp, xw, yw) {
|
|
454
|
+
var f = KIT.enq * 1.12, cx = comp.width / 2, cy = comp.height / 2;
|
|
455
|
+
return { x: cx + (xw - cx) / f, y: cy + (yw - cy + KIT.enqDy) / f };
|
|
456
|
+
}
|
|
457
|
+
function kZonaMundo(comp, texto) {
|
|
458
|
+
var W = comp.width, H = comp.height, alto = H / W > 1.6;
|
|
459
|
+
if (!texto) return { x0: W * KIT.MX, x1: W * (1 - KIT.MX), y0: H * KIT.MX, y1: H * (1 - KIT.MX) };
|
|
460
|
+
return { x0: W * KIT.MX, x1: W * (1 - KIT.MX), y0: alto ? H * 0.14 : H * KIT.MX, y1: alto ? H * (KIT.enqDy > 0 ? 0.73 : 0.8) : H * (1 - KIT.MX) };
|
|
461
|
+
}
|
|
462
|
+
function kZonaTexto(comp, texto) { // em coordenadas de LAYOUT: {x (margem esquerda e direita), top, bot (margem de baixo)}
|
|
463
|
+
var W = comp.width, H = comp.height, z = kZonaMundo(comp, texto !== false), a = kParaLayout(comp, z.x0, z.y0), b = kParaLayout(comp, z.x1, z.y1);
|
|
464
|
+
return { x: a.x, top: a.y, bot: H - b.y };
|
|
465
|
+
}
|
|
466
|
+
function kEhCam(p) { return !!p && (p.name == 'CAM' || p.name == 'CONTEUDO'); }
|
|
467
|
+
function kAreaSegura(comp, o) { return !o.livre && (!o.parent || kEhCam(o.parent)); }
|
|
468
|
+
function texto(comp, str, o) {
|
|
469
|
+
o = o || {};
|
|
470
|
+
var T = KIT.tipo || {};
|
|
471
|
+
var fonte = o.fonte || (KIT.marca && KIT.marca.titulo) || 'Poppins';
|
|
472
|
+
var fonteD = o.fonteDestaque || (KIT.marca && KIT.marca.destaque) || fonte;
|
|
473
|
+
var realce = o.realce || T.realce || 'italico';
|
|
474
|
+
if (realce != 'italico') fonteD = fonte;
|
|
475
|
+
var cor = o.cor || '#FFFFFF', corD = o.corDestaque || cor;
|
|
476
|
+
var tam = (o.tamanho || 90) * KIT.ajuste * KIT.ajusteCena;
|
|
477
|
+
var W = comp.width, H = comp.height, seg = kAreaSegura(comp, o);
|
|
478
|
+
if (T.caixa == 'alta' && o.caixa !== false) str = String(str).toUpperCase();
|
|
479
|
+
var x = o.x == null ? W / 2 : o.x, y = o.y == null ? H / 2 : o.y;
|
|
480
|
+
if (o.opcional && KIT.semRotulos) return { camadas: [], tempos: [], w: 0, h: 0, fim: o.t0 || 0, tam: 0, linhas: 0 };
|
|
481
|
+
var tall = H / W > 1.6, princ = !!o.principal && tall;
|
|
482
|
+
if (kEhCam(o.parent || null) || !o.parent) tam = Math.max(tam, H * 0.036 * (o.principal ? 1 : 1)); // nenhum texto fora de aparelho abaixo de 3,2% da altura (no mundo)
|
|
483
|
+
if (princ) tam = Math.max(tam, 120); // texto principal ≥ 7% da altura do quadro no 9:16 (linha de ~134 px)
|
|
484
|
+
var maxW = o.largura || W * 0.84, maxLin = (o.maxLinhas || 4) + (princ ? 1 : 0);
|
|
485
|
+
if (seg) maxW = Math.min(maxW, W * (1 - 2 * KIT.MX));
|
|
486
|
+
var pal = kPalavras(str);
|
|
487
|
+
if (!pal.length) return { camadas: [], w: 0, h: 0, fim: o.t0 || 0, tam: tam, linhas: 0 };
|
|
488
|
+
var trk = T.tracking != null ? T.tracking : 0;
|
|
489
|
+
var linhas, ws, sw, i, tent = 0;
|
|
490
|
+
for (;;) {
|
|
491
|
+
ws = []; for (i = 0; i < pal.length; i++) ws.push(kMedir(comp, pal[i].t, pal[i].kw ? fonteD : fonte, tam, trk));
|
|
492
|
+
sw = Math.max(tam * 0.27, kMedir(comp, 'a a', fonte, tam, trk) - kMedir(comp, 'aa', fonte, tam, trk));
|
|
493
|
+
var mx = 0; for (i = 0; i < ws.length; i++) if (ws[i] > mx) mx = ws[i];
|
|
494
|
+
linhas = kQuebra(ws, sw, maxW);
|
|
495
|
+
if (linhas.length > 1) { // equilibra: linhas de tamanho parecido
|
|
496
|
+
var tot = 0; for (i = 0; i < ws.length; i++) tot += ws[i] + sw;
|
|
497
|
+
var alvo = Math.max(mx, tot / linhas.length * 1.12);
|
|
498
|
+
var l2 = kQuebra(ws, sw, Math.min(maxW, alvo));
|
|
499
|
+
if (l2.length <= linhas.length) linhas = l2;
|
|
500
|
+
}
|
|
501
|
+
if ((mx <= maxW && linhas.length <= maxLin) || tent > 14 || tam < (princ ? 112 : H * 0.036)) break;
|
|
502
|
+
tam *= 0.92; tent++;
|
|
503
|
+
}
|
|
504
|
+
var lh = tam * (o.entreLinhas || T.entreLinhas || 1.12), bloco = linhas.length * lh, camadas = [], tempos = [], wMax = 0, fim = o.t0 || 0, t0 = o.t0 || 0;
|
|
505
|
+
var k, l, idx = 0, lastT = t0;
|
|
506
|
+
for (l = 0; l < linhas.length; l++) { var lw0 = 0; for (k = 0; k < linhas[l].length; k++) lw0 += ws[linhas[l][k]] + (k ? sw : 0); if (lw0 > wMax) wMax = lw0; }
|
|
507
|
+
if (seg) { // encaixa na área segura: 8% nos lados; no 9:16 respeita as faixas de UI do Reels (14% em cima, 20% embaixo)
|
|
508
|
+
var zs = kZonaTexto(comp), mxp = zs.x, myp = zs.top, myb = zs.bot;
|
|
509
|
+
x = Math.max(mxp + wMax / 2, Math.min(W - mxp - wMax / 2, x));
|
|
510
|
+
y = Math.max(myp + bloco / 2, Math.min(H - myb - bloco / 2, y));
|
|
511
|
+
x = Math.round(x / 8) * 8; y = Math.round(y / 8) * 8; // grade de 8 px
|
|
512
|
+
}
|
|
513
|
+
wMax = 0;
|
|
514
|
+
for (l = 0; l < linhas.length; l++) {
|
|
515
|
+
var lw = 0; for (k = 0; k < linhas[l].length; k++) lw += ws[linhas[l][k]] + (k ? sw : 0);
|
|
516
|
+
if (lw > wMax) wMax = lw;
|
|
517
|
+
var xs = x - lw / 2, yb = y - bloco / 2 + lh * l + lh * 0.5 + tam * 0.33;
|
|
518
|
+
for (k = 0; k < linhas[l].length; k++) {
|
|
519
|
+
var j = linhas[l][k], w = ws[j], xc = xs + w / 2; xs += w + sw;
|
|
520
|
+
var ti = t0 + idx * (o.passo || T.passo || 0.1);
|
|
521
|
+
if (KIT.voz && o.fala !== false) { var tv = kFalaBusca(pal[j].t); ti = tv != null ? tv : Math.max(lastT + 0.08, 0.25); }
|
|
522
|
+
lastT = ti;
|
|
523
|
+
var corTxtCaixa = kLum(corD) > 0.5 ? '#14110F' : '#FFFFFF';
|
|
524
|
+
if (pal[j].kw && realce == 'caixa' && o.sublinhado !== false) { // o marca-texto vem ANTES: o texto entra por cima
|
|
525
|
+
var bw2 = w + tam * 0.3;
|
|
526
|
+
var cx2 = forma(comp, 'retangulo', { x: xc - bw2 / 2, y: yb - tam * 0.3, w: bw2, h: tam * 1.0, r: tam * 0.12, cor: corD, parent: o.parent, nome: 'marca-texto' });
|
|
527
|
+
kA(cx2).setValue([-bw2 / 2, 0]);
|
|
528
|
+
curva(kS(cx2), [[ti, [0, 100], null, 30], [ti + 0.3, [100, 100], 80, null]]);
|
|
529
|
+
}
|
|
530
|
+
var L = comp.layers.addText(pal[j].t); L.name = (o.semAuditoria ? 'fundo-palavra ' : 'palavra ') + pal[j].t;
|
|
531
|
+
if (o.parent) kPai(L, o.parent);
|
|
532
|
+
var kwCor = pal[j].kw ? ((realce == 'caixa') ? corTxtCaixa : corD) : cor;
|
|
533
|
+
kDoc(L, pal[j].kw ? fonteD : fonte, tam * (pal[j].kw ? (o.escalaDestaque || 1.0) : 1), kwCor, { tracking: trk });
|
|
534
|
+
kP(L).setValue([xc, yb]);
|
|
535
|
+
L.comment = ti.toFixed(3); // o instante (nominal) em que a palavra entra: a auditoria usa
|
|
536
|
+
if (o.titulo) { KIT.titulosL = KIT.titulosL || []; KIT.titulosL.push(L); }
|
|
537
|
+
kAnimaPalavra(comp, L, o.entrada || T.entrada || 'palavra', ti, xc, yb, w, tam, l, idx, pal[j].t);
|
|
538
|
+
if (pal[j].kw && realce != 'cor' && realce != 'caixa' && o.sublinhado !== false) {
|
|
539
|
+
var ub = forma(comp, 'pilula', { x: xc - w / 2, y: yb + tam * 0.16, w: w, h: Math.max(6, tam * 0.07), cor: corD, parent: o.parent, nome: 'sublinhado' });
|
|
540
|
+
kA(ub).setValue([-w / 2, 0]);
|
|
541
|
+
curva(kS(ub), [[ti + 0.2, [0, 100], null, 30], [ti + 0.62, [100, 100], 80, null]]);
|
|
542
|
+
}
|
|
543
|
+
camadas.push(L); tempos.push(ti); fim = Math.max(fim, ti + 0.5); idx++;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
var tIni = tempos.length ? tempos[0] : t0;
|
|
547
|
+
if (!o.parent || kEhCam(o.parent)) KIT.rects.push({ espaco: (o.parent && o.parent.name == 'CONTEUDO') ? 'c' : 't', titulo: !!o.titulo, livre: !seg, cena: KIT.cenaIdx, x0: x - wMax / 2, x1: x + wMax / 2, y0: y - bloco / 2, y1: y + bloco / 2, t0: tIni, t1: comp.duration, tam: tam, texto: true, nome: String(str).slice(0, 30), sobrepoe: o.sobrepoe === true });
|
|
548
|
+
if (princ && tam * 1.2 < H * 0.07 - 2) KIT.avisos.push('cena ' + KIT.cenaIdx + ': texto principal pequeno (' + Math.round(tam * 1.2) + ' px < 7% da altura): ' + String(str).slice(0, 30));
|
|
549
|
+
if (wMax > W * (1 - 2 * KIT.MX) + 4 && seg) KIT.avisos.push('cena ' + KIT.cenaIdx + ': texto largo demais: ' + String(str).slice(0, 40));
|
|
550
|
+
return { camadas: camadas, tempos: tempos, w: wMax, h: bloco, fim: fim, tam: tam, linhas: linhas.length, x: x, y: y };
|
|
551
|
+
}
|
|
552
|
+
function kQuebra(ws, sw, maxW) {
|
|
553
|
+
var linhas = [[]], larg = 0, i;
|
|
554
|
+
for (i = 0; i < ws.length; i++) {
|
|
555
|
+
var add = ws[i] + (linhas[linhas.length - 1].length ? sw : 0);
|
|
556
|
+
if (larg + add > maxW && linhas[linhas.length - 1].length) { linhas.push([i]); larg = ws[i]; }
|
|
557
|
+
else { linhas[linhas.length - 1].push(i); larg += add; }
|
|
558
|
+
}
|
|
559
|
+
return linhas;
|
|
560
|
+
}
|
|
561
|
+
function kAnimaPalavra(comp, L, modo, ti, x, y, w, tam, linha, idx, txt) {
|
|
562
|
+
kMarcaEntrada(ti);
|
|
563
|
+
var drift = Math.max(2, tam / 55);
|
|
564
|
+
if (modo == 'letra' || modo == 'voa') {
|
|
565
|
+
// um animador por caractere. 'letra': opacidade 0 + deslocamento; 'voa': a letra chega de longe, grande e girando,
|
|
566
|
+
// em ordem aleatória (Randomize Order) e com suavização, como as letras voando dos reels de motion.
|
|
567
|
+
var an = L.property('ADBE Text Properties').property('ADBE Text Animators').addProperty('ADBE Text Animator');
|
|
568
|
+
var pr = an.property('ADBE Text Animator Properties');
|
|
569
|
+
pr.addProperty('ADBE Text Opacity').setValue(0);
|
|
570
|
+
pr.addProperty('ADBE Text Position 3D').setValue(modo == 'voa' ? [-tam * 0.5, -tam * 1.1, 0] : [0, tam * 0.35, 0]);
|
|
571
|
+
if (modo == 'voa') {
|
|
572
|
+
try { pr.addProperty('ADBE Text Scale 3D').setValue([320, 320, 320]); pr.addProperty('ADBE Text Rotation').setValue(80); } catch (e) { }
|
|
573
|
+
}
|
|
574
|
+
var sel = an.property('ADBE Text Selectors').addProperty('ADBE Text Selector');
|
|
575
|
+
try {
|
|
576
|
+
sel.property('Advanced').property('basedOn').setValue(2);
|
|
577
|
+
sel.property('Advanced').property('smoothness').setValue(modo == 'voa' ? 100 : 0);
|
|
578
|
+
if (modo == 'voa') sel.property('Advanced').property('randomize').setValue(1);
|
|
579
|
+
} catch (e) { }
|
|
580
|
+
var n = Math.max(1, txt.length), dur = (modo == 'voa' ? 0.3 : 0.12) + n * (modo == 'voa' ? 0.06 : 0.045);
|
|
581
|
+
curva(sel.property('ADBE Text Percent Start'), [[ti, 0, null, 30], [ti + dur, 100, 60, null]]);
|
|
582
|
+
kP(L).expression = 'value + [Math.sin(time*1.9+' + idx + ')*' + drift.toFixed(1) + ', Math.cos(time*1.5+' + idx + ')*' + drift.toFixed(1) + ']';
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (modo == 'mascara') {
|
|
586
|
+
var m = kMascaraRect(L, -w / 2 - 20, -tam * 1.0, w / 2 + 20, tam * 0.4, 0);
|
|
587
|
+
var cheio = kRetShape(-w / 2 - 20, -tam * 1.0, w / 2 + 20, tam * 0.4, 0), vazio = kRetShape(-w / 2 - 20, tam * 0.4, w / 2 + 20, tam * 0.4, 0);
|
|
588
|
+
m.setValueAtTime(kFrame(ti), vazio); m.setValueAtTime(kFrame(ti) + 0.4, cheio);
|
|
589
|
+
mola(kP(L), ti, [x, y + tam * 0.6], [x, y], { quique: 0.7, dur: 0.6 });
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (modo == 'sobe') {
|
|
593
|
+
mola(kP(L), ti, [x, y + tam * 1.0], [x, y], { quique: 0.75, dur: 0.65 });
|
|
594
|
+
curva(kO(L), [[ti, 0, null, 30], [ti + 0.16, 100, 60, null]]);
|
|
595
|
+
kS(L).expression = 'var s = value; var k = 1 + 0.014 * Math.sin(time*2.2+' + idx + '); [s[0]*k, s[1]*k]';
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
// 'palavra': estala de ZERO a ~125% e assenta (sobe do chão, balança e respira)
|
|
599
|
+
mola(kP(L), ti, [x, y + tam * 0.7], [x, y], { quique: 0.75, dur: 0.65 });
|
|
600
|
+
mola(kS(L), ti, [0, 0], [100, 100], { quique: 0.84, dur: 0.62 });
|
|
601
|
+
mola(kR(L), ti, (idx % 2 ? 1 : -1) * 10, 0, { quique: 0.7, dur: 0.6 });
|
|
602
|
+
curva(kO(L), [[ti, 0, null, 30], [ti + 0.05, 100, 60, null]]);
|
|
603
|
+
kP(L).expression = 'value + [Math.sin(time*1.9+' + idx + ')*' + drift.toFixed(1) + ', Math.cos(time*1.5+' + idx + ')*' + drift.toFixed(1) + ']';
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// ---------------------------------------------------------------- imagem
|
|
607
|
+
function imagem(comp, arquivo, o) {
|
|
608
|
+
o = o || {};
|
|
609
|
+
var f = new File(arquivo), L;
|
|
610
|
+
var w = o.w || 600, h = o.h || 600;
|
|
611
|
+
var it;
|
|
612
|
+
try { it = app.project.importFile(new ImportOptions(f)); } catch (er) { KIT.avisos.push('imagem não achada: ' + arquivo); L = forma(comp, 'retangulo', { x: o.x, y: o.y, w: w, h: h, cor: '#888888', parent: o.parent, r: o.r }); return L; }
|
|
613
|
+
L = comp.layers.add(it); L.name = o.nome || 'imagem';
|
|
614
|
+
if (o.parent) kPai(L, o.parent);
|
|
615
|
+
var k = Math.max(w / it.width, h / it.height) * 100; // cobre a caixa (cover)
|
|
616
|
+
kS(L).setValue([k, k]);
|
|
617
|
+
kP(L).setValue([o.x == null ? comp.width / 2 : o.x, o.y == null ? comp.height / 2 : o.y]);
|
|
618
|
+
// máscara na caixa (em coordenadas da camada: antes da escala, em px da imagem)
|
|
619
|
+
var mw = w / k * 100 / 2, mh = h / k * 100 / 2;
|
|
620
|
+
kMascaraRect(L, it.width / 2 - mw, it.height / 2 - mh, it.width / 2 + mw, it.height / 2 + mh, (o.r || 0) / k * 100);
|
|
621
|
+
kA(L).setValue([it.width / 2, it.height / 2]);
|
|
622
|
+
if (o.entrada) kEntrada(L, o.t0 || 0, o.entrada, o.quique);
|
|
623
|
+
return L;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// ---------------------------------------------------------------- celular
|
|
627
|
+
/* celular(comp, {tela, x, y, escala, parent, t0, entrada}): um iPhone de formas.
|
|
628
|
+
tela = '#cor' (ou caminho de imagem). Devolve {no, tela:{w,h}, toque(t,lx,ly), ...}.
|
|
629
|
+
As coordenadas locais têm a origem no centro da tela; 1 unidade = 1 px do celular a 100%. */
|
|
630
|
+
function celular(comp, o) {
|
|
631
|
+
o = o || {};
|
|
632
|
+
var no = comp.layers.addNull(comp.duration); no.name = 'celular'; no.enabled = false;
|
|
633
|
+
if (o.parent) kPai(no, o.parent);
|
|
634
|
+
var esc = (o.escala || 1) * 100;
|
|
635
|
+
kA(no).setValue([0, 0]);
|
|
636
|
+
kP(no).setValue([o.x == null ? comp.width / 2 : o.x, o.y == null ? comp.height / 2 : o.y]);
|
|
637
|
+
kS(no).setValue([esc, esc]);
|
|
638
|
+
var C = { no: no, comp: comp, tela: { w: 430, h: 920 }, filhos: [], dedo: null, fim: 0 };
|
|
639
|
+
var corpo = forma(comp, 'retangulo', { x: 0, y: 0, w: 470, h: 960, r: 84, cor: o.corpo || '#17171C', traco: '#4A4A55', tracoL: 5, parent: no, nome: 'corpo' });
|
|
640
|
+
var tc = o.tela || '#F6F6F8', telaL;
|
|
641
|
+
if (String(tc).charAt(0) == '#') telaL = forma(comp, 'retangulo', { x: 0, y: 0, w: 430, h: 920, r: 66, cor: tc, parent: no, nome: 'tela' });
|
|
642
|
+
else telaL = imagem(comp, tc, { x: 0, y: 0, w: 430, h: 920, r: 66, parent: no, nome: 'tela' });
|
|
643
|
+
var ilha = forma(comp, 'pilula', { x: 0, y: -418, w: 128, h: 36, cor: '#050507', parent: no, nome: 'ilha' });
|
|
644
|
+
var barra = forma(comp, 'pilula', { x: 0, y: 424, w: 140, h: 6, cor: '#101014', alfa: 55, parent: no, nome: 'barra' });
|
|
645
|
+
C.corpo = corpo; C.telaL = telaL; C.ilha = ilha;
|
|
646
|
+
// entrada do conjunto: sobe do chão, gira um pouco e assenta
|
|
647
|
+
var t0 = o.t0 || 0, x = kP(no).value[0], y = kP(no).value[1];
|
|
648
|
+
if (o.entrada !== false) {
|
|
649
|
+
mola(kP(no), t0, [x, y + comp.height * 0.18], [x, y], { quique: 0.4, dur: 0.85 });
|
|
650
|
+
mola(kR(no), t0, -7, 0, { quique: 0.5, dur: 0.9 });
|
|
651
|
+
mola(kS(no), t0, [esc * 0.82, esc * 0.82], [esc, esc], { quique: 0.4, dur: 0.8 });
|
|
652
|
+
som(t0 + 0.05, 'toque', 0.9);
|
|
653
|
+
}
|
|
654
|
+
/* toque(t, lx, ly, {nome}): o dedo (um círculo translúcido) vai até o ponto, afunda e solta uma onda. */
|
|
655
|
+
C.toque = function (t, lx, ly, op) {
|
|
656
|
+
op = op || {};
|
|
657
|
+
if (!C.dedo) {
|
|
658
|
+
C.dedo = forma(comp, 'circulo', { x: 0, y: 520, w: 70, cor: '#FFFFFF', alfa: 0, parent: no, nome: 'dedo' });
|
|
659
|
+
C.dedoPos = [60, 520];
|
|
660
|
+
kP(C.dedo).setValue([60, 520]);
|
|
661
|
+
C.dedo.property('ADBE Effect Parade').addProperty('ADBE Drop Shadow');
|
|
662
|
+
}
|
|
663
|
+
var d = C.dedo, de = C.dedoPos;
|
|
664
|
+
curva(kP(d), [[t - 0.5, de, 30, 20], [t - 0.04, [lx, ly], 78, 30]]);
|
|
665
|
+
curva(kO(d), [[t - 0.5, de[1] > 400 ? 0 : 85, null, 30], [t - 0.3, 85, 60, 30]]);
|
|
666
|
+
curva(kS(d), [[t - 0.04, [100, 100], null, 25], [t + 0.06, [72, 72], 70, 40], [t + 0.22, [100, 100], 70, null]]);
|
|
667
|
+
C.dedoPos = [lx + 40, ly + 70];
|
|
668
|
+
var r = forma(comp, 'circulo', { x: lx, y: ly, w: 90, traco: op.cor || '#FFFFFF', tracoL: 6, alfa: 0, parent: no, nome: 'onda' });
|
|
669
|
+
curva(kS(r), [[t, [30, 30], null, 20], [t + 0.45, [210, 210], 80, null]]);
|
|
670
|
+
curva(kO(r), [[t - 0.04, 0, null, 30], [t, 70, null, 30], [t + 0.45, 0, 70, null]]);
|
|
671
|
+
som(t, 'clique', 0.9);
|
|
672
|
+
C.fim = Math.max(C.fim, t + 0.45);
|
|
673
|
+
return r;
|
|
674
|
+
};
|
|
675
|
+
C.sai = function (t) { // o dedo some
|
|
676
|
+
if (C.dedo) curva(kO(C.dedo), [[t, 85, null, 30], [t + 0.25, 0, 60, null]]);
|
|
677
|
+
};
|
|
678
|
+
return C;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/* botao(comp, {x,y,w,h,rotulo,cor,corTexto,parent,t0}) + botao.aperta(t): o botão que afunda e volta. */
|
|
682
|
+
function botao(comp, o) {
|
|
683
|
+
var b = forma(comp, 'pilula', { x: o.x, y: o.y, w: o.w || 360, h: o.h || 110, cor: o.cor || '#FFFFFF', parent: o.parent, nome: 'botao', entrada: o.entrada === false ? null : 'pop', t0: o.t0 || 0, quique: 0.6 });
|
|
684
|
+
var tx = texto(comp, o.rotulo || 'Toque aqui', { x: o.x, y: o.y, tamanho: o.tam || 44, cor: o.corTexto || '#000000', parent: o.parent, entrada: 'sobe', t0: (o.t0 || 0) + 0.08, largura: (o.w || 360) * 0.86, maxLinhas: 1, fonte: o.fonte });
|
|
685
|
+
return { forma: b, texto: tx, aperta: function (t) {
|
|
686
|
+
// 100%: o valor lido de uma propriedade com chaves é o do tempo 0 (a mola de entrada começa em 0)
|
|
687
|
+
curva(kS(b), [[t, [100, 100], null, 25], [t + 0.07, [90, 90], 70, 40], [t + 0.25, [100, 100], 70, null]]);
|
|
688
|
+
som(t, 'clique', 0.9);
|
|
689
|
+
} };
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// ---------------------------------------------------------------- trocas de cena
|
|
693
|
+
/* troca(cenaA, cenaB, t, tipo): cenaA e cenaB são camadas (comps de cena) na MAIN; a troca roda em [t, t+DUR]. B entra
|
|
694
|
+
por cima de A. TROCAS (15): encolhe · empurra · mascara · zoom · flash · persiana · chicote · desfoque · cortina ·
|
|
695
|
+
pontos · giro · tremor · abre · dissolve · corte. */
|
|
696
|
+
var TROCA_DUR = 0.45;
|
|
697
|
+
var TROCAS_TODAS = ['encolhe', 'empurra', 'mascara', 'zoom', 'persiana', 'chicote', 'desfoque', 'cortina', 'pontos', 'giro', 'tremor', 'abre', 'dissolve', 'corte'];
|
|
698
|
+
function kBlur(L, de, para, t, d) {
|
|
699
|
+
var b = kFx(L, 'ADBE Gaussian Blur 2');
|
|
700
|
+
curva(b.property('ADBE Gaussian Blur 2-0001'), [[t, de, null, 25], [t + d, para, 75, null]]);
|
|
701
|
+
}
|
|
702
|
+
function kMascaraAnim(L, de, para, t, d) {
|
|
703
|
+
var m = L.property('ADBE Mask Parade').addProperty('ADBE Mask Atom');
|
|
704
|
+
var p = m.property('ADBE Mask Shape');
|
|
705
|
+
p.setValue(de);
|
|
706
|
+
p.setValueAtTime(kFrame(t), de);
|
|
707
|
+
p.setValueAtTime(kFrame(t) + d, para);
|
|
708
|
+
return m;
|
|
709
|
+
}
|
|
710
|
+
function troca(cenaA, cenaB, t, tipo, cor) {
|
|
711
|
+
var comp = KIT.main || cenaA.containingComp, W = comp.width, H = comp.height, cx = W / 2, cy = H / 2, d = TROCA_DUR, i, u = Math.min(W, H) / 1080;
|
|
712
|
+
tipo = tipo || 'encolhe';
|
|
713
|
+
var vert = H > W, R = Math.sqrt(W * W + H * H) / 2 + 20;
|
|
714
|
+
cor = cor || '#FFFFFF';
|
|
715
|
+
if (tipo == 'empurra') {
|
|
716
|
+
var fora = vert ? [cx, cy - H] : [cx - W, cy], de = vert ? [cx, cy + H] : [cx + W, cy];
|
|
717
|
+
curva(kP(cenaA), [[t, [cx, cy], null, 25], [t + d, fora, 78, null]]);
|
|
718
|
+
curva(kP(cenaB), [[t, de, null, 25], [t + d, [cx, cy], 78, null]]);
|
|
719
|
+
} else if (tipo == 'mascara') {
|
|
720
|
+
kMascaraAnim(cenaB, kCircShape(cx, cy, 2), kCircShape(cx, cy, R), t, d + 0.1);
|
|
721
|
+
curva(kS(cenaA), [[t, [100, 100], null, 30], [t + d + 0.1, [108, 108], 70, null]]);
|
|
722
|
+
} else if (tipo == 'zoom') {
|
|
723
|
+
curva(kS(cenaA), [[t, [100, 100], null, 22], [t + d, [190, 190], 80, null]]);
|
|
724
|
+
curva(kO(cenaA), [[t + d * 0.3, 100, null, 30], [t + d, 0, 70, null]]);
|
|
725
|
+
curva(kS(cenaB), [[t, [58, 58], null, 22], [t + d, [100, 100], 80, null]]);
|
|
726
|
+
curva(kO(cenaB), [[t, 0, null, 30], [t + d * 0.6, 100, 70, null]]);
|
|
727
|
+
} else if (tipo == 'persiana') {
|
|
728
|
+
var n = 6;
|
|
729
|
+
for (i = 0; i < n; i++) {
|
|
730
|
+
var f0 = vert ? [0, i * H / n, W, i * H / n] : [i * W / n, 0, i * W / n, H], f1 = vert ? [0, i * H / n, W, (i + 1) * H / n + 2] : [i * W / n, 0, (i + 1) * W / n + 2, H];
|
|
731
|
+
kMascaraAnim(cenaB, kRetShape(f0[0], f0[1], f0[2], f0[3], 0), kRetShape(f1[0], f1[1], f1[2], f1[3], 0), t + i * 0.035, d * 0.7);
|
|
732
|
+
}
|
|
733
|
+
} else if (tipo == 'chicote') {
|
|
734
|
+
var dx = W * 0.9;
|
|
735
|
+
curva(kP(cenaA), [[t, [cx, cy], null, 15], [t + d * 0.8, [cx - dx, cy], 85, null]]);
|
|
736
|
+
kBlur(cenaA, 0, 26 * u, t, d * 0.8);
|
|
737
|
+
curva(kP(cenaB), [[t + d * 0.1, [cx + dx, cy], null, 15], [t + d, [cx, cy], 85, null]]);
|
|
738
|
+
kBlur(cenaB, 26 * u, 0, t + d * 0.1, d * 0.9);
|
|
739
|
+
} else if (tipo == 'desfoque') {
|
|
740
|
+
kBlur(cenaA, 0, 24 * u, t, d); curva(kO(cenaA), [[t, 100, null, 25], [t + d, 0, 75, null]]);
|
|
741
|
+
kBlur(cenaB, 24 * u, 0, t, d); curva(kO(cenaB), [[t, 0, null, 25], [t + d, 100, 75, null]]);
|
|
742
|
+
} else if (tipo == 'cortina') {
|
|
743
|
+
var pn = comp.layers.addSolid(kCor(cor), 'cortina', W, H, 1);
|
|
744
|
+
var d0 = vert ? [cx, cy + H] : [cx + W, cy], d1 = [cx, cy], d2 = vert ? [cx, cy - H] : [cx - W, cy];
|
|
745
|
+
curva(kP(pn), [[t, d0, null, 20], [t + d * 0.5, d1, 70, 20], [t + d, d2, 70, null]]);
|
|
746
|
+
curva(kO(cenaB), [[t, 0, null, null], [t + d * 0.5, 100, null, null]]);
|
|
747
|
+
curva(kO(cenaA), [[t + d * 0.5, 100, null, null], [t + d * 0.5 + 0.1, 0, null, null]]);
|
|
748
|
+
} else if (tipo == 'pontos') {
|
|
749
|
+
var cols = vert ? 3 : 5, rows = vert ? 5 : 3, rr = Math.max(W / cols, H / rows) * 0.78;
|
|
750
|
+
for (i = 0; i < cols * rows; i++) {
|
|
751
|
+
var c0 = i % cols, r0 = Math.floor(i / cols), px = (c0 + 0.5) * W / cols, py = (r0 + 0.5) * H / rows;
|
|
752
|
+
kMascaraAnim(cenaB, kCircShape(px, py, 1), kCircShape(px, py, rr), t + (c0 + r0) * 0.03, d * 0.7);
|
|
753
|
+
}
|
|
754
|
+
} else if (tipo == 'giro') {
|
|
755
|
+
curva(kR(cenaA), [[t, 0, null, 25], [t + d, -22, 78, null]]);
|
|
756
|
+
curva(kS(cenaA), [[t, [100, 100], null, 25], [t + d, [60, 60], 78, null]]);
|
|
757
|
+
curva(kO(cenaA), [[t, 100, null, 25], [t + d, 0, 78, null]]);
|
|
758
|
+
curva(kR(cenaB), [[t, 22, null, 25], [t + d, 0, 78, null]]);
|
|
759
|
+
curva(kS(cenaB), [[t, [140, 140], null, 25], [t + d, [100, 100], 78, null]]);
|
|
760
|
+
curva(kO(cenaB), [[t, 0, null, 25], [t + d * 0.6, 100, 78, null]]);
|
|
761
|
+
} else if (tipo == 'tremor') {
|
|
762
|
+
var tk = [], tk2 = [];
|
|
763
|
+
for (i = 0; i < 7; i++) { var jx = (i % 2 ? 1 : -1) * (46 - i * 5) * u, jy = (i % 3 - 1) * (24 - i * 3) * u; tk.push([t + i * 0.033, [cx + jx, cy + jy], -1, -1]); tk2.push([t + 0.1 + i * 0.033, [cx - jx * 0.6, cy - jy * 0.6], -1, -1]); }
|
|
764
|
+
tk.unshift([t - 0.1, [cx, cy], null, null]); // antes da troca a cena fica CENTRADA (a 1ª chave de jitter deslocava a cena e mostrava a borda da comp)
|
|
765
|
+
tk.push([t + 0.26, [cx, cy], -1, null]); curva(kP(cenaA), tk);
|
|
766
|
+
curva(kO(cenaA), [[t + 0.06, 100, null, null], [t + 0.14, 0, null, null]]);
|
|
767
|
+
curva(kO(cenaB), [[t + 0.04, 0, null, null], [t + 0.12, 100, null, null]]);
|
|
768
|
+
tk2.unshift([t, [cx, cy], null, null]);
|
|
769
|
+
tk2.push([t + 0.36, [cx, cy], -1, null]); curva(kP(cenaB), tk2);
|
|
770
|
+
} else if (tipo == 'abre') {
|
|
771
|
+
var rw = vert ? [0, cy - 4, W, cy + 4] : [cx - 4, 0, cx + 4, H], rf = [0, 0, W, H];
|
|
772
|
+
kMascaraAnim(cenaB, kRetShape(rw[0], rw[1], rw[2], rw[3], 0), kRetShape(rf[0], rf[1], rf[2], rf[3], 0), t, d);
|
|
773
|
+
} else if (tipo == 'dissolve') {
|
|
774
|
+
curva(kO(cenaA), [[t, 100, null, 30], [t + d, 0, 70, null]]);
|
|
775
|
+
curva(kO(cenaB), [[t, 0, null, 30], [t + d, 100, 70, null]]);
|
|
776
|
+
curva(kS(cenaB), [[t, [104, 104], null, 30], [t + d, [100, 100], 70, null]]);
|
|
777
|
+
} else if (tipo == 'corte') {
|
|
778
|
+
curva(kO(cenaB), [[t - 0.08, 0, null, null], [t, 100, null, null]]);
|
|
779
|
+
curva(kS(cenaB), [[t, [109, 109], null, 18], [t + 0.28, [100, 100], 80, null]]);
|
|
780
|
+
} else { // encolhe: A afunda e some, B cresce de fora para o quadro
|
|
781
|
+
curva(kS(cenaA), [[t, [100, 100], null, 25], [t + d, [72, 72], 78, null]]);
|
|
782
|
+
curva(kO(cenaA), [[t, 100, null, 25], [t + d, 0, 78, null]]);
|
|
783
|
+
curva(kS(cenaB), [[t, [128, 128], null, 25], [t + d, [100, 100], 78, null]]);
|
|
784
|
+
curva(kO(cenaB), [[t, 0, null, 25], [t + d * 0.7, 100, 78, null]]);
|
|
785
|
+
}
|
|
786
|
+
// o som da troca em CAMADAS: riser antes, whoosh na virada, impacto e sub-drop no pouso (o Node escolhe um arquivo diferente para cada)
|
|
787
|
+
som(Math.max(0.02, t - 0.62), 'sobe', 0.5);
|
|
788
|
+
som(t - 0.05, 'troca', 0.85);
|
|
789
|
+
som(t + 0.12, 'impacto', 0.7); som(t + 0.12, 'sub', 0.5);
|
|
790
|
+
if (tipo == 'tremor' || tipo == 'corte') som(t - 0.02, 'glitch', 0.4);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// ---------------------------------------------------------------- elementos reais, caminhos, partículas
|
|
794
|
+
/* elemento(comp, i|obj, {x,y,w,h,parent,t0,entrada,quique,flutua,nome}): um elemento REAL do assunto (PNG/SVG/sequência de
|
|
795
|
+
PNG de um GIF animado), encaixado na caixa w×h sem cortar. KIT.elementos vem do plano (Node baixou e converteu). */
|
|
796
|
+
function kElem(i) { var n = KIT.elementos.length; return n ? KIT.elementos[(((i + KIT.cenaIdx) % n) + n) % n] : null; } // cada cena começa por um elemento diferente
|
|
797
|
+
function kPoeEl(comp, it, e, o, t) {
|
|
798
|
+
var L = comp.layers.add(it); L.name = o.nome || ('el ' + e.nome);
|
|
799
|
+
if (o.parent) kPai(L, o.parent);
|
|
800
|
+
var w = o.w || 300, h = o.h || w, k = Math.min(w / it.width, h / it.height) * 100;
|
|
801
|
+
kS(L).setValue([k, k]);
|
|
802
|
+
kP(L).setValue([o.x == null ? comp.width / 2 : o.x, o.y == null ? comp.height / 2 : o.y]);
|
|
803
|
+
if (t) L.startTime = t;
|
|
804
|
+
if (o.rot) kR(L).setValue(o.rot);
|
|
805
|
+
return L;
|
|
806
|
+
}
|
|
807
|
+
function elemento(comp, e, o) {
|
|
808
|
+
o = o || {};
|
|
809
|
+
if (typeof e == 'number') e = kElem(e);
|
|
810
|
+
var w = o.w || 300, h = o.h || w, L = null;
|
|
811
|
+
if ((!o.parent || kEhCam(o.parent)) && w < comp.width * 0.12 && o.nome != 'ambiente') { var kk = comp.width * 0.12 / w; w *= kk; h *= kk; o.w = w; o.h = h; } // ícone de apoio ≥ 12% da largura
|
|
812
|
+
if ((!o.parent || kEhCam(o.parent)) && o.x != null) { var ze0 = kZonaTexto(comp, false); o.x = Math.max(ze0.x + w / 2, Math.min(comp.width - ze0.x - w / 2, Math.round(o.x / 8) * 8)); o.y = Math.max(ze0.top + h / 2, Math.min(comp.height - ze0.bot - h / 2, Math.round(o.y / 8) * 8)); if (o.nome != 'ambiente') KIT.rects.push({ espaco: (o.parent && o.parent.name == 'CONTEUDO') ? 'c' : 't', cena: KIT.cenaIdx, x0: o.x - w / 2, x1: o.x + w / 2, y0: o.y - h / 2, y1: o.y + h / 2, t0: 0, t1: 1, texto: false, sobrepoe: true, nome: 'elemento ' + (e && e.nome || '') }); }
|
|
813
|
+
if (!e) {
|
|
814
|
+
L = forma(comp, 'circulo', { x: o.x, y: o.y, w: Math.min(w, h) * 0.85, cor: o.corFallback || '#8A8A8A', parent: o.parent, nome: 'elemento-reserva' });
|
|
815
|
+
} else {
|
|
816
|
+
KIT.cache = KIT.cache || {};
|
|
817
|
+
var it = KIT.cache[e.arquivo];
|
|
818
|
+
if (!it) {
|
|
819
|
+
var op = new ImportOptions(new File(e.arquivo));
|
|
820
|
+
if (e.tipo == 'seq') op.sequence = true;
|
|
821
|
+
try { it = app.project.importFile(op); KIT.cache[e.arquivo] = it; }
|
|
822
|
+
catch (er) { KIT.avisos.push('cena ' + KIT.cenaIdx + ': elemento não importou: ' + e.arquivo); it = null; }
|
|
823
|
+
}
|
|
824
|
+
if (!it) return elemento(comp, null, o);
|
|
825
|
+
L = kPoeEl(comp, it, e, o, o.t0 && e.tipo == 'seq' ? o.t0 : 0);
|
|
826
|
+
if (e.tipo == 'seq' && it.duration > 0.1) { // o GIF acaba em ~1 s: repete até o fim da cena
|
|
827
|
+
var n, dur = it.duration, ini = (o.t0 || 0) + dur;
|
|
828
|
+
for (n = 0; n < 12 && ini < comp.duration; n++, ini += dur) kPoeEl(comp, it, e, o, ini);
|
|
829
|
+
}
|
|
830
|
+
KIT.nElem = (KIT.nElem || 0) + 1;
|
|
831
|
+
}
|
|
832
|
+
L.comment = String(o.t0 || 0);
|
|
833
|
+
if (o.entrada) kEntrada(L, o.t0 || 0, o.entrada, o.quique);
|
|
834
|
+
if (o.flutua) {
|
|
835
|
+
var a = o.flutua * Math.min(comp.width, comp.height) / 1080, ph = (o.fase || 0);
|
|
836
|
+
kP(L).expression = 'value + [Math.sin(time*1.7+' + ph + ')*' + a.toFixed(1) + ', Math.cos(time*1.3+' + ph + ')*' + (a * 1.1).toFixed(1) + ']';
|
|
837
|
+
}
|
|
838
|
+
return L;
|
|
839
|
+
}
|
|
840
|
+
// sombra de contato: uma elipse borrada no chão do objeto
|
|
841
|
+
function sombraChao(comp, x, y, w, o) {
|
|
842
|
+
o = o || {};
|
|
843
|
+
var L = forma(comp, 'circulo', { x: x, y: y, w: w, cor: o.cor || '#000000', alfa: o.alfa == null ? 28 : o.alfa, parent: o.parent, nome: 'sombra' });
|
|
844
|
+
kS(L).setValue([100, 26]);
|
|
845
|
+
try { var b = kFx(L, 'ADBE Gaussian Blur 2'); b.property('ADBE Gaussian Blur 2-0001').setValue(w * 0.09); } catch (e) { }
|
|
846
|
+
if (o.t0 != null) curva(kO(L), [[o.t0, 0, null, 30], [o.t0 + 0.4, o.alfa == null ? 28 : o.alfa, 60, null]]);
|
|
847
|
+
return L;
|
|
848
|
+
}
|
|
849
|
+
/* caminho(comp, pontos, {cor, esp, t0, dur, parent, fecha, preenche, suave}): polilinha (ou polígono) com o traço desenhado por trim. */
|
|
850
|
+
function caminho(comp, pts, o) {
|
|
851
|
+
o = o || {};
|
|
852
|
+
var L = comp.layers.addShape(); L.name = o.nome || 'caminho'; L.comment = 'caminho'; // o sourceRect de um caminho absoluto inclui a origem: fica fora da medida do herói
|
|
853
|
+
if (o.parent) kPai(L, o.parent);
|
|
854
|
+
var g = L.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
855
|
+
var v = g.property('ADBE Vectors Group');
|
|
856
|
+
var pa = v.addProperty('ADBE Vector Shape - Group');
|
|
857
|
+
var S = new Shape(), vs = [], it = [], ot = [], i;
|
|
858
|
+
for (i = 0; i < pts.length; i++) { vs.push([pts[i][0], pts[i][1]]); it.push([0, 0]); ot.push([0, 0]); }
|
|
859
|
+
if (o.suave) {
|
|
860
|
+
for (i = 1; i < pts.length - 1; i++) { var dx = (pts[i + 1][0] - pts[i - 1][0]) / 6, dy = (pts[i + 1][1] - pts[i - 1][1]) / 6; it[i] = [-dx, -dy]; ot[i] = [dx, dy]; }
|
|
861
|
+
if (pts.length > 1) { ot[0] = [(pts[1][0] - pts[0][0]) / 3, (pts[1][1] - pts[0][1]) / 3]; it[pts.length - 1] = [-(pts[pts.length - 1][0] - pts[pts.length - 2][0]) / 3, -(pts[pts.length - 1][1] - pts[pts.length - 2][1]) / 3]; }
|
|
862
|
+
}
|
|
863
|
+
S.vertices = vs; S.inTangents = it; S.outTangents = ot; S.closed = !!o.fecha;
|
|
864
|
+
pa.property('ADBE Vector Shape').setValue(S);
|
|
865
|
+
if (o.preenche) v.addProperty('ADBE Vector Graphic - Fill').property('ADBE Vector Fill Color').setValue(kCor(o.preenche));
|
|
866
|
+
if (o.cor) {
|
|
867
|
+
var st = v.addProperty('ADBE Vector Graphic - Stroke');
|
|
868
|
+
st.property('ADBE Vector Stroke Color').setValue(kCor(o.cor));
|
|
869
|
+
st.property('ADBE Vector Stroke Width').setValue(o.esp || 8);
|
|
870
|
+
try { st.property('ADBE Vector Stroke Line Cap').setValue(2); st.property('ADBE Vector Stroke Line Join').setValue(2); } catch (e) { }
|
|
871
|
+
}
|
|
872
|
+
kP(L).setValue([0, 0]);
|
|
873
|
+
if (o.alfa != null) kO(L).setValue(o.alfa);
|
|
874
|
+
if (o.t0 != null && o.dur) {
|
|
875
|
+
var tm = v.addProperty('ADBE Vector Filter - Trim');
|
|
876
|
+
curva(tm.property('ADBE Vector Trim End'), [[o.t0, 0, null, 20], [o.t0 + o.dur, 100, 80, null]]);
|
|
877
|
+
}
|
|
878
|
+
return L;
|
|
879
|
+
}
|
|
880
|
+
/* grupo(comp, parent, x, y): um null para agrupar peças que se movem juntas (câmera em cadeia, cartões, painéis). */
|
|
881
|
+
function grupo(comp, o) {
|
|
882
|
+
o = o || {};
|
|
883
|
+
var no = comp.layers.addNull(comp.duration); no.name = o.nome || 'grupo'; no.enabled = false;
|
|
884
|
+
if (o.parent) kPai(no, o.parent);
|
|
885
|
+
kA(no).setValue([0, 0]);
|
|
886
|
+
kP(no).setValue([o.x == null ? comp.width / 2 : o.x, o.y == null ? comp.height / 2 : o.y]);
|
|
887
|
+
if (o.esc) kS(no).setValue([o.esc * 100, o.esc * 100]);
|
|
888
|
+
return no;
|
|
889
|
+
}
|
|
890
|
+
/* particulas(comp, {n, cor, parent, tipo:'sobe'|'cai'|'flutua', raio, area:[x0,y0,x1,y1], t0}) */
|
|
891
|
+
function particulas(comp, o) {
|
|
892
|
+
o = o || {};
|
|
893
|
+
var n = o.n || 24, i, W = comp.width, H = comp.height, u = Math.min(W, H) / 1080, ar = o.area || [0, 0, W, H], out = [];
|
|
894
|
+
for (i = 0; i < n; i++) {
|
|
895
|
+
var rnd = function (k) { var q = Math.sin((i + 1) * 12.9898 + k * 78.233) * 43758.5453; return q - Math.floor(q); };
|
|
896
|
+
var r = (o.raio || 14) * u * (0.5 + rnd(1)), x = ar[0] + rnd(2) * (ar[2] - ar[0]), y = ar[1] + rnd(3) * (ar[3] - ar[1]);
|
|
897
|
+
var L = forma(comp, o.forma || 'circulo', { x: x, y: y, w: r * 2, h: r * 2 * (o.forma == 'retangulo' ? 0.5 : 1), cor: (o.cores ? o.cores[i % o.cores.length] : o.cor || '#FFFFFF'), parent: o.parent, nome: 'particula', alfa: 0 });
|
|
898
|
+
var vel = 0.12 + rnd(4) * 0.2, off = rnd(5), amp = (20 + rnd(6) * 40) * u, f = 0.8 + rnd(7) * 1.6, dir = o.tipo == 'cai' ? 1 : -1, alc = (ar[3] - ar[1]) * (o.tipo == 'flutua' ? 0.12 : 0.8);
|
|
899
|
+
kP(L).expression = 'var p = value; var q = ((time * ' + vel.toFixed(3) + ' + ' + off.toFixed(3) + ') % 1); [p[0] + Math.sin(time * ' + f.toFixed(2) + ' + ' + (i * 1.7).toFixed(2) + ') * ' + amp.toFixed(1) + ', p[1] + ' + dir + ' * q * ' + alc.toFixed(1) + ']';
|
|
900
|
+
kO(L).expression = 'var q = ((time * ' + vel.toFixed(3) + ' + ' + off.toFixed(3) + ') % 1); Math.sin(Math.PI * q) * ' + (o.alfa || 70) + ' * (time > ' + (o.t0 || 0) + ' ? 1 : 0)';
|
|
901
|
+
if (o.gira) kR(L).expression = 'time * ' + (30 + rnd(8) * 90).toFixed(0);
|
|
902
|
+
out.push(L);
|
|
903
|
+
}
|
|
904
|
+
return out;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// ---------------------------------------------------------------- legenda por palavra (na MAIN)
|
|
908
|
+
/* legenda(main, chunks, o): faixa escura arredondada com o trecho falado; a palavra já dita acende, a palavra-chave
|
|
909
|
+
fica na cor de destaque. chunks = [{t, t2, palavras:[{w, t, t2, chave}]}] (maquina-voz.js legendaChunks). */
|
|
910
|
+
function legenda(main, chunks, o) {
|
|
911
|
+
o = o || {};
|
|
912
|
+
var W = main.width, H = main.height, u = Math.min(W, H) / 1080, tam0 = (o.tamanho || 54) * u, fonte = o.fonte || 'Poppins';
|
|
913
|
+
var yc = H * (o.y || 0.905), c, i, l;
|
|
914
|
+
for (c = 0; c < chunks.length; c++) {
|
|
915
|
+
var ch = chunks[c], P = ch.palavras, tam = tam0, sw = tam * 0.28;
|
|
916
|
+
// a FRASE inteira, em até 2 linhas equilibradas (nunca um fragmento)
|
|
917
|
+
var total = 0; for (i = 0; i < P.length; i++) total += P[i].w.length + 1;
|
|
918
|
+
var nl = total > 34 ? 2 : 1, linhas = [[]], acum = 0;
|
|
919
|
+
for (i = 0; i < P.length; i++) { if (nl == 2 && linhas.length == 1 && acum + P[i].w.length / 2 > total / 2 && linhas[0].length) linhas.push([]); linhas[linhas.length - 1].push(i); acum += P[i].w.length + 1; }
|
|
920
|
+
var ws = [], lw = [], maxLw = 0;
|
|
921
|
+
for (i = 0; i < P.length; i++) ws.push(kMedir(main, P[i].w, P[i].chave ? (o.fonteDestaque || fonte) : fonte, tam));
|
|
922
|
+
for (l = 0; l < linhas.length; l++) { var t0w = 0, q; for (q = 0; q < linhas[l].length; q++) t0w += ws[linhas[l][q]] + (q ? sw : 0); lw.push(t0w); maxLw = Math.max(maxLw, t0w); }
|
|
923
|
+
var esc = maxLw > W * 0.88 ? W * 0.88 / maxLw : 1;
|
|
924
|
+
if (esc < 1) { tam *= esc; sw *= esc; for (i = 0; i < ws.length; i++) ws[i] *= esc; for (l = 0; l < lw.length; l++) lw[l] *= esc; maxLw *= esc; }
|
|
925
|
+
var t = ch.t, t2 = Math.max(ch.t2, ch.t + 0.25), fim = c + 1 < chunks.length ? Math.min(t2 + 0.3, chunks[c + 1].t) : t2 + 0.3;
|
|
926
|
+
var lh = tam * 1.45, hp = linhas.length * lh + tam * 0.35, ytop = yc - (linhas.length - 1) * lh / 2;
|
|
927
|
+
var pill = forma(main, 'pilula', { x: W / 2, y: yc, w: maxLw + tam * 1.2, h: hp, cor: o.fundo || '#000000', alfa: o.alfaFundo == null ? 62 : o.alfaFundo, nome: 'legenda-fundo' });
|
|
928
|
+
pill.inPoint = t - 0.04; pill.outPoint = fim;
|
|
929
|
+
for (l = 0; l < linhas.length; l++) {
|
|
930
|
+
var xs = W / 2 - lw[l] / 2, yy = ytop + l * lh;
|
|
931
|
+
for (q = 0; q < linhas[l].length; q++) {
|
|
932
|
+
i = linhas[l][q];
|
|
933
|
+
var p = P[i], cx = xs + ws[i] / 2; xs += ws[i] + sw;
|
|
934
|
+
var L = main.layers.addText(p.w); L.name = 'legenda ' + p.w;
|
|
935
|
+
kDoc(L, p.chave ? (o.fonteDestaque || fonte) : fonte, tam, p.chave ? (o.corDestaque || '#FFD54A') : '#FFFFFF');
|
|
936
|
+
kP(L).setValue([cx, yy + tam * 0.34]);
|
|
937
|
+
L.inPoint = t - 0.04; L.outPoint = fim;
|
|
938
|
+
var op = kO(L), tp = Math.max(p.t, t);
|
|
939
|
+
op.setValueAtTime(kFrame(t - 0.04), 42);
|
|
940
|
+
if (kFrame(tp) > kFrame(t - 0.04) + 0.02) { op.setValueAtTime(kFrame(tp) - 1 / KIT.fps, 42); }
|
|
941
|
+
op.setValueAtTime(kFrame(tp), 100);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// ---------------------------------------------------------------- conferência de layout (por cena)
|
|
948
|
+
/* Fora da área segura e sobreposição de textos que existem juntos: escreve "AVISO cena N: ..." para o Node refazer. */
|
|
949
|
+
function kRectLayout(r) {
|
|
950
|
+
if (r.espaco != 'c' || !KIT.remap) return r;
|
|
951
|
+
var m = KIT.remap, q = {}, k;
|
|
952
|
+
for (k in r) q[k] = r[k];
|
|
953
|
+
q.x0 = m.px + (r.x0 - m.ax) * m.s; q.x1 = m.px + (r.x1 - m.ax) * m.s;
|
|
954
|
+
q.y0 = m.py + (r.y0 - m.ay) * m.s; q.y1 = m.py + (r.y1 - m.ay) * m.s;
|
|
955
|
+
return q;
|
|
956
|
+
}
|
|
957
|
+
function kConfereCena(comp) {
|
|
958
|
+
if (KIT.cenaHeroi) { // cena de herói: o elemento maior ocupa ≥ 45% da largura útil
|
|
959
|
+
var hmax = 0, hh;
|
|
960
|
+
for (hh = 0; hh < KIT.rects.length; hh++) { var rr0 = KIT.rects[hh]; if (rr0.cena == KIT.cenaIdx && !rr0.texto && String(rr0.nome).indexOf('elemento') == 0) hmax = Math.max(hmax, rr0.x1 - rr0.x0); }
|
|
961
|
+
if (hmax > 0 && hmax < comp.width * 0.84 * 0.45 - 2) KIT.avisos.push('cena ' + KIT.cenaIdx + ': herói pequeno (' + Math.round(hmax) + ' px < 45% da largura útil)');
|
|
962
|
+
}
|
|
963
|
+
var W = comp.width, H = comp.height, R = KIT.rects, i, j, a, b, zt = kZonaTexto(comp, true), ze = kZonaTexto(comp, false), mx = ze.x - 2, my = ze.top - 2;
|
|
964
|
+
var mine = [];
|
|
965
|
+
for (i = 0; i < R.length; i++) if (R[i].cena == KIT.cenaIdx && !R[i].conferido) { R[i].conferido = true; mine.push(kRectLayout(R[i])); }
|
|
966
|
+
for (i = 0; i < mine.length; i++) {
|
|
967
|
+
a = mine[i];
|
|
968
|
+
if (a.banda) continue;
|
|
969
|
+
for (j = 0; j < mine.length; j++) if (mine[j].banda && !a.titulo) { b = mine[j]; if (a.x0 < b.x1 && a.x1 > b.x0 && a.y0 < b.y1 - 2 && a.y1 > b.y0 + 2 && !a.livre) KIT.avisos.push('cena ' + KIT.cenaIdx + ': invade a faixa do título: ' + String(a.nome).slice(0, 30)); }
|
|
970
|
+
if (a.livre) continue;
|
|
971
|
+
if (a.espaco == 'c' && KIT.remap) continue; // com o conteúdo ajustado à zona, quem mede é a auditoria quadro a quadro (matrizes reais)
|
|
972
|
+
if (a.texto) { if (a.x0 < zt.x - 6 || a.x1 > W - zt.x + 6 || a.y0 < zt.top - 6 || a.y1 > H - zt.bot + 6) KIT.avisos.push('cena ' + KIT.cenaIdx + ': texto fora da área segura: ' + a.nome); }
|
|
973
|
+
else if (a.x0 < mx || a.x1 > W - mx || a.y0 < my || a.y1 > H - ze.bot + 2) KIT.avisos.push('cena ' + KIT.cenaIdx + ': elemento fora da área segura: ' + a.nome);
|
|
974
|
+
for (j = i + 1; j < mine.length; j++) {
|
|
975
|
+
b = mine[j];
|
|
976
|
+
if (a.sobrepoe || b.sobrepoe || a.livre || b.livre || !a.texto || !b.texto) continue;
|
|
977
|
+
if (Math.max(a.t0, b.t0) >= Math.min(a.t1, b.t1) - 0.2) continue;
|
|
978
|
+
var ox = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0), oy = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0);
|
|
979
|
+
if (ox > 4 && oy > 4) {
|
|
980
|
+
var ar = Math.min((a.x1 - a.x0) * (a.y1 - a.y0), (b.x1 - b.x0) * (b.y1 - b.y0));
|
|
981
|
+
if (ox * oy > ar * 0.1) KIT.avisos.push('cena ' + KIT.cenaIdx + ': textos se sobrepõem: ' + a.nome + ' / ' + b.nome);
|
|
982
|
+
} else if (ox > 4 && oy <= 4) { // um acima do outro: respiro mínimo = metade da altura do texto
|
|
983
|
+
var gap = -oy, min = 0.5 * Math.min(a.tam || 0, b.tam || 0);
|
|
984
|
+
if (gap < min - 1) KIT.avisos.push('cena ' + KIT.cenaIdx + ': pouco espaço entre textos (' + Math.round(gap) + ' < ' + Math.round(min) + ' px): ' + a.nome + ' / ' + b.nome);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// ---------------------------------------------------------------- quando as coisas entram (a regra dos 30–40%)
|
|
991
|
+
/* kEntradaMax(comp): o instante (nominal) em que a ÚLTIMA camada de conteúdo fica visível, lido das chaves de opacidade, e o que
|
|
992
|
+
kEntrada/kAnimaPalavra registraram. Cursor, ondas, partículas e atmosfera não contam: não são elementos novos. */
|
|
993
|
+
var KIT_NAO_ENTRADA = /^(fundo|brilho|vazamento|look|flash|ambiente|CAM|particula|sombra|onda|estouro|halo|cursor|dedo|seta|grade|rua|terra|rio|tampa|guia|linha-skel|barra-rolagem|digitando|badge)/;
|
|
994
|
+
function kEntradaMax(comp) {
|
|
995
|
+
var mx = KIT.entMax, i;
|
|
996
|
+
for (i = 1; i <= comp.numLayers; i++) {
|
|
997
|
+
var L = comp.layer(i);
|
|
998
|
+
if (KIT_NAO_ENTRADA.test(L.name) || L.nullLayer) continue;
|
|
999
|
+
try {
|
|
1000
|
+
var tr = L.property('ADBE Transform Group'), vis = L.inPoint, k, t0;
|
|
1001
|
+
var op = tr.property('ADBE Opacity');
|
|
1002
|
+
if (op.numKeys > 0 && !op.expressionEnabled) { t0 = null; for (k = 1; k <= op.numKeys; k++) { if (op.keyValue(k) >= 40) { t0 = op.keyTime(k); break; } } if (t0 != null && t0 > vis) vis = t0; }
|
|
1003
|
+
var sc = tr.property('ADBE Scale');
|
|
1004
|
+
if (sc.numKeys > 0 && !sc.expressionEnabled) { t0 = null; for (k = 1; k <= sc.numKeys; k++) { if (sc.keyValue(k)[0] >= 40) { t0 = sc.keyTime(k); break; } } if (t0 != null && t0 > vis) vis = t0; }
|
|
1005
|
+
var cm = (L.comment != null && L.comment !== '') ? parseFloat(L.comment) : NaN;
|
|
1006
|
+
if (!isNaN(cm) && cm > vis) vis = cm;
|
|
1007
|
+
if (vis > mx) mx = vis;
|
|
1008
|
+
} catch (e) { }
|
|
1009
|
+
}
|
|
1010
|
+
return mx;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// ---------------------------------------------------------------- auditoria quadro a quadro
|
|
1014
|
+
/* kAuditoria(comp): a cada 0,1 s (tempo real) mede a caixa de cada texto e de cada elemento JÁ com escala, posição, pais e câmera
|
|
1015
|
+
(matriz do layer × matriz dos pais, sourceRectAtTime para texto) e reprova: (1) fora da área segura, (2) colisão entre caixas visíveis
|
|
1016
|
+
no mesmo instante (texto sobre texto/elemento; só fundo e atmosfera ficam atrás). Só conta o que já assentou (entrada + 0,5 s) e
|
|
1017
|
+
termina antes da troca. Escreve "AVISO cena N: ..." (a máquina corrige e refaz) e "AUDIT {json}" com as contagens. */
|
|
1018
|
+
function kMulMat(m, n) { return [m[0] * n[0] + m[2] * n[1], m[1] * n[0] + m[3] * n[1], m[0] * n[2] + m[2] * n[3], m[1] * n[2] + m[3] * n[3], m[0] * n[4] + m[2] * n[5] + m[4], m[1] * n[4] + m[3] * n[5] + m[5]]; }
|
|
1019
|
+
function kMatLocal(L, t) {
|
|
1020
|
+
var tr = L.property('ADBE Transform Group');
|
|
1021
|
+
var p = tr.property('ADBE Position').valueAtTime(t, false), s = tr.property('ADBE Scale').valueAtTime(t, false), r = tr.property('ADBE Rotate Z').valueAtTime(t, false), an = tr.property('ADBE Anchor Point').valueAtTime(t, false);
|
|
1022
|
+
var rad = r * Math.PI / 180, cs = Math.cos(rad), sn = Math.sin(rad), sx = s[0] / 100, sy = s[1] / 100;
|
|
1023
|
+
var a = cs * sx, b = sn * sx, c = -sn * sy, d = cs * sy;
|
|
1024
|
+
return [a, b, c, d, p[0] - a * an[0] - c * an[1], p[1] - b * an[0] - d * an[1]];
|
|
1025
|
+
}
|
|
1026
|
+
function kMatMundo(L, t, cache) {
|
|
1027
|
+
var k = L.index;
|
|
1028
|
+
if (cache[k]) return cache[k];
|
|
1029
|
+
var m = kMatLocal(L, t);
|
|
1030
|
+
if (L.parent) m = kMulMat(kMatMundo(L.parent, t, cache), m);
|
|
1031
|
+
cache[k] = m;
|
|
1032
|
+
return m;
|
|
1033
|
+
}
|
|
1034
|
+
function kCaixaMundo(L, t, cache) {
|
|
1035
|
+
var r, m = kMatMundo(L, t, cache);
|
|
1036
|
+
if (L.name.indexOf('palavra ') == 0) { var q = L.sourceRectAtTime(t, false); r = [q.left, q.top, q.left + q.width, q.top + q.height]; }
|
|
1037
|
+
else { var sw = L.source ? L.source.width : 0, sh = L.source ? L.source.height : 0; r = [0, 0, sw, sh]; }
|
|
1038
|
+
var xs = [r[0], r[2], r[0], r[2]], ys = [r[1], r[1], r[3], r[3]], i, X = [], Y = [];
|
|
1039
|
+
for (i = 0; i < 4; i++) { X.push(m[0] * xs[i] + m[2] * ys[i] + m[4]); Y.push(m[1] * xs[i] + m[3] * ys[i] + m[5]); }
|
|
1040
|
+
return [Math.min(X[0], X[1], X[2], X[3]), Math.min(Y[0], Y[1], Y[2], Y[3]), Math.max(X[0], X[1], X[2], X[3]), Math.max(Y[0], Y[1], Y[2], Y[3])];
|
|
1041
|
+
}
|
|
1042
|
+
var KIT_SKIP_CADEIA = /^(feed|mapa|parede|pan|zoom|celular|janela|papel|carimbo|slot|carta)/;
|
|
1043
|
+
function kAuditoria(comp) {
|
|
1044
|
+
if (KIT.auditoria === false) return;
|
|
1045
|
+
var W = comp.width, H = comp.height, f = KIT.f || 1, zT = kZonaMundo(comp, true), zE = kZonaMundo(comp, false), i, j, k;
|
|
1046
|
+
var cand = [];
|
|
1047
|
+
for (i = 1; i <= comp.numLayers; i++) {
|
|
1048
|
+
var L = comp.layer(i), nm = L.name;
|
|
1049
|
+
var ehTexto = nm.indexOf('palavra ') == 0, ehEl = nm.indexOf('el ') == 0 || nm == 'elemento-reserva' || nm == 'ambiente';
|
|
1050
|
+
if (!ehTexto && !ehEl) continue;
|
|
1051
|
+
var skip = false, P = L.parent;
|
|
1052
|
+
while (P) { if (KIT_SKIP_CADEIA.test(P.name)) { skip = true; break; } P = P.parent; }
|
|
1053
|
+
var nominal = (L.comment != null && L.comment !== '') ? parseFloat(L.comment) : 0;
|
|
1054
|
+
if (isNaN(nominal)) nominal = 0;
|
|
1055
|
+
cand.push({ L: L, nome: nm, texto: ehTexto, skip: skip, entra: nominal, amb: nm == 'ambiente' });
|
|
1056
|
+
}
|
|
1057
|
+
var passo = 0.1 * f, dur = comp.duration, fim = dur - 0.55 * f, t, amostras = 0, nFora = 0, nCol = 0, vistos = {}, exs = 0;
|
|
1058
|
+
for (t = 0.3 * f; t < fim; t += passo) {
|
|
1059
|
+
var cache = {}, vis = [];
|
|
1060
|
+
for (i = 0; i < cand.length; i++) {
|
|
1061
|
+
var c = cand[i];
|
|
1062
|
+
if (c.skip || t < c.entra + 0.5 * f) continue;
|
|
1063
|
+
try {
|
|
1064
|
+
var tr = c.L.property('ADBE Transform Group');
|
|
1065
|
+
if (tr.property('ADBE Opacity').valueAtTime(t, false) < 40) continue;
|
|
1066
|
+
if (t < c.L.inPoint || t >= c.L.outPoint) continue;
|
|
1067
|
+
var bx = kCaixaMundo(c.L, t, cache);
|
|
1068
|
+
if (bx[2] - bx[0] < 2 || bx[3] - bx[1] < 2) continue;
|
|
1069
|
+
var h0 = bx[3] - bx[1];
|
|
1070
|
+
vis.push({ c: c, b: bx, tinta: c.texto ? [bx[0], bx[1] + h0 * 0.14, bx[2], bx[3] - h0 * 0.14] : bx });
|
|
1071
|
+
} catch (e) { }
|
|
1072
|
+
}
|
|
1073
|
+
amostras++;
|
|
1074
|
+
var foraT = false, colT = false;
|
|
1075
|
+
for (i = 0; i < vis.length; i++) {
|
|
1076
|
+
var a = vis[i], b = a.b;
|
|
1077
|
+
var zz = a.c.texto ? zT : zE, limX0 = zz.x0, limX1 = zz.x1, limY0 = zz.y0, limY1 = zz.y1;
|
|
1078
|
+
if (b[0] < limX0 - 8 || b[2] > limX1 + 8 || b[1] < limY0 - 8 || b[3] > limY1 + 8) {
|
|
1079
|
+
foraT = true;
|
|
1080
|
+
var kf = 'f:' + a.c.nome;
|
|
1081
|
+
if (!vistos[kf] && exs < 8) { vistos[kf] = 1; exs++; KIT.avisos.push('cena ' + KIT.cenaIdx + ': ' + (a.c.texto ? 'texto' : 'elemento') + ' fora da área segura (quadro ' + (t / f).toFixed(1) + ' s): ' + a.c.nome.replace('palavra ', '') + ' [' + Math.round(b[0]) + ',' + Math.round(b[1]) + ',' + Math.round(b[2]) + ',' + Math.round(b[3]) + ']'); }
|
|
1082
|
+
}
|
|
1083
|
+
for (j = i + 1; j < vis.length; j++) {
|
|
1084
|
+
var bt = a.tinta, o2 = vis[j].tinta, ox = Math.min(bt[2], o2[2]) - Math.max(bt[0], o2[0]), oy = Math.min(bt[3], o2[3]) - Math.max(bt[1], o2[1]);
|
|
1085
|
+
if (ox > 5 && oy > 5) {
|
|
1086
|
+
var A1 = (bt[2] - bt[0]) * (bt[3] - bt[1]), A2 = (o2[2] - o2[0]) * (o2[3] - o2[1]);
|
|
1087
|
+
if (ox * oy > 0.05 * Math.min(A1, A2)) {
|
|
1088
|
+
colT = true;
|
|
1089
|
+
var kc = 'c:' + a.c.nome + '|' + vis[j].c.nome;
|
|
1090
|
+
if (!vistos[kc] && exs < 8) { vistos[kc] = 1; exs++; KIT.avisos.push('cena ' + KIT.cenaIdx + ': colisão (quadro ' + (t / f).toFixed(1) + ' s): ' + a.c.nome.replace('palavra ', '') + ' x ' + vis[j].c.nome.replace('palavra ', '')); }
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
if (foraT) nFora++;
|
|
1096
|
+
if (colT) nCol++;
|
|
1097
|
+
}
|
|
1098
|
+
writeLn('AUDIT ' + JSON.stringify({ cena: KIT.cenaIdx, amostras: amostras, foraDaArea: nFora, colisoes: nCol }));
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// ---------------------------------------------------------------- o herói ocupa a zona dele inteira
|
|
1102
|
+
function kMatRel(L, t, cache, stop) {
|
|
1103
|
+
var k = L.index;
|
|
1104
|
+
if (cache[k]) return cache[k];
|
|
1105
|
+
var m = kMatLocal(L, t);
|
|
1106
|
+
if (L.parent && L.parent.index != stop) m = kMulMat(kMatRel(L.parent, t, cache, stop), m);
|
|
1107
|
+
cache[k] = m;
|
|
1108
|
+
return m;
|
|
1109
|
+
}
|
|
1110
|
+
var KIT_NAO_CONTA = /^(fundo|antes-fundo|depois-fundo|brilho|vazamento|look|ambiente|particula|sombra|estouro|onda|halo|cursor|dedo|tampa|guia|CAM|CONTEUDO)/;
|
|
1111
|
+
/* kAjustaConteudo(comp, cam): mede a caixa do CONTEÚDO (tudo que é filho do CONTEUDO, já assentado) e põe essa caixa na zona dele —
|
|
1112
|
+
entre a faixa reservada do título (+24 px) e o fim da zona segura —, escalando de 70% a 140% e centrando. Cena sem título (ou com
|
|
1113
|
+
mapa, feed, parede… que sangram de propósito) fica como foi desenhada. */
|
|
1114
|
+
function kAjustaConteudo(comp, cam) {
|
|
1115
|
+
if (!cam || !cam.camNo || KIT.tituloB == null || KIT.fit === false) return;
|
|
1116
|
+
var W = comp.width, H = comp.height, cont = cam.no, dur = comp.duration, i, k, ts = [0.45 * dur, 0.6 * dur];
|
|
1117
|
+
var x0 = 1e9, y0 = 1e9, x1 = -1e9, y1 = -1e9, n = 0;
|
|
1118
|
+
for (i = 1; i <= comp.numLayers; i++) {
|
|
1119
|
+
var L = comp.layer(i);
|
|
1120
|
+
if (KIT_NAO_CONTA.test(L.name) || L.nullLayer || L.comment == 'caminho') continue;
|
|
1121
|
+
var P = L.parent, dentro = false;
|
|
1122
|
+
while (P) { if (P.index == cont.index) { dentro = true; break; } if (KIT_SKIP_CADEIA.test(P.name) && P.name != 'celular' && P.name != 'janela' && P.name != 'papel' && P.name != 'carimbo') return; P = P.parent; }
|
|
1123
|
+
if (!dentro) continue;
|
|
1124
|
+
for (k = 0; k < ts.length; k++) {
|
|
1125
|
+
var t = ts[k];
|
|
1126
|
+
try {
|
|
1127
|
+
if (t < L.inPoint || t >= L.outPoint) continue;
|
|
1128
|
+
if (L.property('ADBE Transform Group').property('ADBE Opacity').valueAtTime(t, false) < 40) continue;
|
|
1129
|
+
var cache = {}, m = kMatRel(L, t, cache, cont.index), r;
|
|
1130
|
+
if (L.name.indexOf('palavra ') == 0) { var q = L.sourceRectAtTime(t, false); r = [q.left, q.top, q.left + q.width, q.top + q.height]; }
|
|
1131
|
+
else if (L.name.indexOf('el ') == 0 && L.source && L.source.width) r = [0, 0, L.source.width, L.source.height];
|
|
1132
|
+
else { var q2 = L.sourceRectAtTime(t, false); r = [q2.left, q2.top, q2.left + q2.width, q2.top + q2.height]; }
|
|
1133
|
+
var xs = [r[0], r[2], r[0], r[2]], ys = [r[1], r[1], r[3], r[3]], j;
|
|
1134
|
+
for (j = 0; j < 4; j++) { var X = m[0] * xs[j] + m[2] * ys[j] + m[4], Y = m[1] * xs[j] + m[3] * ys[j] + m[5]; if (KIT.debugFit && (X < 20 || Y < 20)) writeLn('FITDBG ' + L.name + ' ' + Math.round(X) + ',' + Math.round(Y)); x0 = Math.min(x0, X); y0 = Math.min(y0, Y); x1 = Math.max(x1, X); y1 = Math.max(y1, Y); }
|
|
1135
|
+
n++;
|
|
1136
|
+
} catch (e) { }
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
if (!n || x1 - x0 < 50 || y1 - y0 < 50) return;
|
|
1140
|
+
var z = kZonaTexto(comp, true), top = KIT.tituloB, bot = H - z.bot, aw = W - 2 * z.x;
|
|
1141
|
+
var s = Math.max(0.7, Math.min(1.4, aw / (x1 - x0), (bot - top) / (y1 - y0)));
|
|
1142
|
+
var bx = (x0 + x1) / 2, by = (y0 + y1) / 2, py = (top + bot) / 2;
|
|
1143
|
+
kA(cont).setValue([bx, by]); kP(cont).setValue([W / 2, py]); kS(cont).setValue([s * 100, s * 100]);
|
|
1144
|
+
KIT.remap = { s: s, ax: bx, ay: by, px: W / 2, py: py };
|
|
1145
|
+
writeLn('FIT ' + JSON.stringify({ cena: KIT.cenaIdx, escala: Math.round(s * 100) / 100, caixa: [Math.round(x0), Math.round(y0), Math.round(x1), Math.round(y1)] }));
|
|
1146
|
+
}
|