primocode 10.16.0 → 10.17.1

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.
Files changed (237) hide show
  1. package/LICENSES/edit-ia-pro.txt +32 -0
  2. package/LICENSES/fontes-OFL.txt +476 -0
  3. package/LICENSES/hyperframes-Apache-2.0.txt +205 -0
  4. package/LICENSES/permanent-marker-Apache-2.0.txt +204 -0
  5. package/LICENSES/selfie-multiclass-Apache-2.0.txt +227 -0
  6. package/LICENSES/three-MIT.txt +23 -0
  7. package/LICENSES/video-use-MIT.txt +24 -0
  8. package/LICENSES/woven-sfx-CC0.txt +16 -0
  9. package/LICENSES/yunet-MIT.txt +21 -0
  10. package/README.md +2 -2
  11. package/bin/primocode.js +28 -8
  12. package/editor/LICENSE.md +11 -0
  13. package/editor/README.md +321 -0
  14. package/editor/SKILL.md +307 -0
  15. package/editor/THIRD_PARTY_NOTICES.md +228 -0
  16. package/editor/assets/baixar.json +591 -0
  17. package/editor/assets/fonts/anton/OFL.txt +93 -0
  18. package/editor/assets/fonts/caveat/OFL.txt +93 -0
  19. package/editor/assets/fonts/figtree/OFL.txt +93 -0
  20. package/editor/assets/fonts/fonts.json +10 -0
  21. package/editor/assets/fonts/montserrat/OFL.txt +93 -0
  22. package/editor/assets/fonts/permanentmarker/LICENSE.txt +202 -0
  23. package/editor/assets/models/SELFIE_MULTICLASS_LICENSE.txt +227 -0
  24. package/editor/assets/models/YUNET_LICENSE.txt +21 -0
  25. package/editor/assets/sfx/licencas/bass_drop.txt +32 -0
  26. package/editor/assets/sfx/licencas/cash.txt +76 -0
  27. package/editor/assets/sfx/licencas/charge.txt +31 -0
  28. package/editor/assets/sfx/licencas/click.txt +46 -0
  29. package/editor/assets/sfx/licencas/coin.txt +50 -0
  30. package/editor/assets/sfx/licencas/count.txt +47 -0
  31. package/editor/assets/sfx/licencas/data.txt +31 -0
  32. package/editor/assets/sfx/licencas/error.txt +32 -0
  33. package/editor/assets/sfx/licencas/flash.txt +31 -0
  34. package/editor/assets/sfx/licencas/gears.txt +82 -0
  35. package/editor/assets/sfx/licencas/keyboard.txt +48 -0
  36. package/editor/assets/sfx/licencas/metal_hit.txt +62 -0
  37. package/editor/assets/sfx/licencas/metal_riser.txt +61 -0
  38. package/editor/assets/sfx/licencas/mouse_click.txt +50 -0
  39. package/editor/assets/sfx/licencas/notification.txt +54 -0
  40. package/editor/assets/sfx/licencas/pop.txt +38 -0
  41. package/editor/assets/sfx/licencas/rewind.txt +32 -0
  42. package/editor/assets/sfx/licencas/rise.txt +46 -0
  43. package/editor/assets/sfx/licencas/sinteticos.txt +21 -0
  44. package/editor/assets/sfx/licencas/snap.txt +50 -0
  45. package/editor/assets/sfx/licencas/success.txt +40 -0
  46. package/editor/assets/sfx/licencas/synth_hit.txt +32 -0
  47. package/editor/assets/sfx/licencas/tick.txt +14 -0
  48. package/editor/assets/sfx/licencas/whoosh.txt +47 -0
  49. package/editor/assets/sfx/licencas/wind.txt +31 -0
  50. package/editor/assets/sfx/sfx.json +832 -0
  51. package/editor/assets/sfx/sfx_sinteticos.json +317 -0
  52. package/editor/assets/sfx/sfx_woven.json +387 -0
  53. package/editor/assets/sfx/woven/LICENCA.md +16 -0
  54. package/editor/fichas/briefing-do-video.md +45 -0
  55. package/editor/fichas/conferencia-da-amostra.md +56 -0
  56. package/editor/fichas/matriz-de-ganchos.csv +3 -0
  57. package/editor/fichas/padrao.json +16 -0
  58. package/editor/fichas/planilha-de-cenas.csv +4 -0
  59. package/editor/fichas/planilha-de-versoes.csv +4 -0
  60. package/editor/fichas/plano-em-blocos.md +32 -0
  61. package/editor/fichas/registro-de-materiais.json +27 -0
  62. package/editor/helpers/assets_ocr/ocr_vision.swift +41 -0
  63. package/editor/helpers/bordas_precisas.py +272 -0
  64. package/editor/helpers/camera_viva.py +426 -0
  65. package/editor/helpers/captions.py +601 -0
  66. package/editor/helpers/common.py +308 -0
  67. package/editor/helpers/compose_final.py +3555 -0
  68. package/editor/helpers/conferir_corte.py +234 -0
  69. package/editor/helpers/conferir_dados.py +405 -0
  70. package/editor/helpers/contact_sheet.py +282 -0
  71. package/editor/helpers/corte_por_onda.py +433 -0
  72. package/editor/helpers/corte_seco.py +595 -0
  73. package/editor/helpers/denoise.py +971 -0
  74. package/editor/helpers/efeitos.py +408 -0
  75. package/editor/helpers/efeitos_gerar.py +159 -0
  76. package/editor/helpers/elevenlabs_api.py +442 -0
  77. package/editor/helpers/face_layout.py +570 -0
  78. package/editor/helpers/fetch_images.py +423 -0
  79. package/editor/helpers/ganho_por_trecho.py +214 -0
  80. package/editor/helpers/gen_image.py +312 -0
  81. package/editor/helpers/gen_music.py +316 -0
  82. package/editor/helpers/gen_sfx.py +148 -0
  83. package/editor/helpers/grade.py +307 -0
  84. package/editor/helpers/icloud.py +119 -0
  85. package/editor/helpers/make_sfx.py +940 -0
  86. package/editor/helpers/matte.py +1342 -0
  87. package/editor/helpers/medir_referencia.py +2232 -0
  88. package/editor/helpers/mixar_trilha.py +354 -0
  89. package/editor/helpers/montar_corte.py +295 -0
  90. package/editor/helpers/motion/__init__.py +13 -0
  91. package/editor/helpers/motion/engine.py +1915 -0
  92. package/editor/helpers/motion/registry.py +510 -0
  93. package/editor/helpers/motion/render.py +665 -0
  94. package/editor/helpers/motion/templates/barra_progresso.py +370 -0
  95. package/editor/helpers/motion/templates/carimbo.py +132 -0
  96. package/editor/helpers/motion/templates/checklist.py +271 -0
  97. package/editor/helpers/motion/templates/comentario_cta.py +380 -0
  98. package/editor/helpers/motion/templates/contador.py +222 -0
  99. package/editor/helpers/motion/templates/destaque.py +263 -0
  100. package/editor/helpers/motion/templates/etiqueta_preco.py +461 -0
  101. package/editor/helpers/motion/templates/grafico_barras.py +510 -0
  102. package/editor/helpers/motion/templates/grafico_linha.py +462 -0
  103. package/editor/helpers/motion/templates/notificacao.py +266 -0
  104. package/editor/helpers/motion/templates/palavra_impacto.py +410 -0
  105. package/editor/helpers/motion/templates/passos.py +321 -0
  106. package/editor/helpers/motion/templates/riscado.py +298 -0
  107. package/editor/helpers/motion/templates/selo_garantia.py +150 -0
  108. package/editor/helpers/motion_render.py +241 -0
  109. package/editor/helpers/motion_sugerir.py +961 -0
  110. package/editor/helpers/noise_check.py +134 -0
  111. package/editor/helpers/pack_transcripts.py +223 -0
  112. package/editor/helpers/palavras_na_onda.py +176 -0
  113. package/editor/helpers/plano_sfx.py +839 -0
  114. package/editor/helpers/portao.py +427 -0
  115. package/editor/helpers/preview_server.py +1177 -0
  116. package/editor/helpers/rastrear_rosto.py +298 -0
  117. package/editor/helpers/render_cut.py +1256 -0
  118. package/editor/helpers/respiros.py +89 -0
  119. package/editor/helpers/sincronizar_cameras.py +571 -0
  120. package/editor/helpers/speech_regions.py +423 -0
  121. package/editor/helpers/style_catalog.json +231 -0
  122. package/editor/helpers/style_samples.py +246 -0
  123. package/editor/helpers/tela_verde.py +2113 -0
  124. package/editor/helpers/text_render.py +2059 -0
  125. package/editor/helpers/texto_na_tela.py +366 -0
  126. package/editor/helpers/timeline_view.py +292 -0
  127. package/editor/helpers/tira_de_quadros.py +113 -0
  128. package/editor/helpers/transcribe.py +734 -0
  129. package/editor/helpers/transcribe_batch.py +129 -0
  130. package/editor/helpers/trilhas.py +1146 -0
  131. package/editor/helpers/trilhas_humores.json +66 -0
  132. package/editor/helpers/valores.py +187 -0
  133. package/editor/helpers/verify_cut.py +820 -0
  134. package/editor/helpers/voice_levels.py +233 -0
  135. package/editor/helpers/voz_check.py +386 -0
  136. package/editor/helpers/voz_limpa.py +81 -0
  137. package/editor/helpers/watch_preview.py +372 -0
  138. package/editor/modelo-projeto/LEIA.md +402 -0
  139. package/editor/modelo-projeto/assets/fontes/OFL-Caveat.txt +93 -0
  140. package/editor/modelo-projeto/assets/fontes/OFL-JetBrainsMono.txt +93 -0
  141. package/editor/modelo-projeto/assets/fontes/OFL-Montserrat.txt +93 -0
  142. package/editor/modelo-projeto/assets/fontes/larguras.json +1 -0
  143. package/editor/modelo-projeto/assets/three/BufferGeometryUtils.js +1438 -0
  144. package/editor/modelo-projeto/assets/three/GLTFLoader.js +4895 -0
  145. package/editor/modelo-projeto/assets/three/LICENSE +21 -0
  146. package/editor/modelo-projeto/assets/three/ORIGEM.txt +17 -0
  147. package/editor/modelo-projeto/assets/three/RoomEnvironment.js +185 -0
  148. package/editor/modelo-projeto/assets/three/three.core.min.js +6 -0
  149. package/editor/modelo-projeto/assets/three/three.module.min.js +6 -0
  150. package/editor/modelo-projeto/build.py +4828 -0
  151. package/editor/modelo-projeto/compositions/cenas/2d/k2d_antes_depois.html +199 -0
  152. package/editor/modelo-projeto/compositions/cenas/2d/k2d_arquivo.html +232 -0
  153. package/editor/modelo-projeto/compositions/cenas/2d/k2d_busca.html +315 -0
  154. package/editor/modelo-projeto/compositions/cenas/2d/k2d_comando.html +304 -0
  155. package/editor/modelo-projeto/compositions/cenas/2d/k2d_conversa.html +217 -0
  156. package/editor/modelo-projeto/compositions/cenas/2d/k2d_esquema.html +289 -0
  157. package/editor/modelo-projeto/compositions/cenas/2d/k2d_medidor.html +249 -0
  158. package/editor/modelo-projeto/compositions/cenas/2d/k2d_notas.html +233 -0
  159. package/editor/modelo-projeto/compositions/cenas/3d/k3d_caminho.html +197 -0
  160. package/editor/modelo-projeto/compositions/cenas/3d/k3d_explodida.html +152 -0
  161. package/editor/modelo-projeto/compositions/cenas/3d/k3d_tela.html +167 -0
  162. package/editor/modelo-projeto/compositions/cenas/3d/k3d_volume.html +124 -0
  163. package/editor/modelo-projeto/compositions/cenas/3d/motor-three.js +728 -0
  164. package/editor/modelo-projeto/compositions/cenas/LEIA.md +177 -0
  165. package/editor/modelo-projeto/ferramentas/medir_fontes.py +65 -0
  166. package/editor/modelo-projeto/ferramentas/pessoa_recortada.py +176 -0
  167. package/editor/modelo-projeto/ferramentas/rastrear_maos.py +189 -0
  168. package/editor/modelo-projeto/hyperframes.json +12 -0
  169. package/editor/modelo-projeto/package.json +11 -0
  170. package/editor/modelo-projeto/projeto.json +16 -0
  171. package/editor/preview/app.css +1009 -0
  172. package/editor/preview/app.js +2122 -0
  173. package/editor/preview/index.html +307 -0
  174. package/editor/pyproject.toml +23 -0
  175. package/editor/references/3d.md +236 -0
  176. package/editor/references/animacao-catalogo.md +672 -0
  177. package/editor/references/animacao.md +498 -0
  178. package/editor/references/comandos.md +92 -0
  179. package/editor/references/corte-seco-como-funciona.md +50 -0
  180. package/editor/references/corte-seco.md +88 -0
  181. package/editor/references/corte.md +290 -0
  182. package/editor/references/direcao-por-blocos.md +218 -0
  183. package/editor/references/enquadramento.md +654 -0
  184. package/editor/references/estilos-prontos.md +355 -0
  185. package/editor/references/estudio.md +100 -0
  186. package/editor/references/exemplo-eventos.json +67 -0
  187. package/editor/references/lettering.md +252 -0
  188. package/editor/references/modelos.md +494 -0
  189. package/editor/references/phase2.md +1007 -0
  190. package/editor/references/referencia-aplicar.md +203 -0
  191. package/editor/references/referencia-medir.md +375 -0
  192. package/editor/references/revisao.md +335 -0
  193. package/editor/references/som-e-trilha.md +146 -0
  194. package/editor/references/tabela-de-sons.md +130 -0
  195. package/editor/references/variacoes.md +234 -0
  196. package/editor/uv.lock +1141 -0
  197. package/lib/act.js +36 -8
  198. package/lib/catalogo.js +4 -0
  199. package/lib/chamada-torta.js +81 -0
  200. package/lib/editor-pro.js +786 -0
  201. package/lib/entrega.js +58 -0
  202. package/lib/estudio/conferencia-visual.js +76 -0
  203. package/lib/estudio/diretor.js +6 -1
  204. package/lib/estudio/exportar.js +3 -1
  205. package/lib/estudio/gosto.js +45 -4
  206. package/lib/estudio/index.js +8 -5
  207. package/lib/estudio/kit-ae/base.jsx +119 -13
  208. package/lib/estudio/kit-ae/cenas.jsx +47 -15
  209. package/lib/estudio/kit-ae/guarda.jsx +274 -0
  210. package/lib/estudio/kit-ae/primitivas.jsx +180 -24
  211. package/lib/estudio/maquina-diretor.js +61 -7
  212. package/lib/estudio/maquina-foto.js +177 -0
  213. package/lib/estudio/maquina-guarda.js +207 -0
  214. package/lib/estudio/maquina-layout.js +22 -1
  215. package/lib/estudio/maquina.js +60 -11
  216. package/lib/estudio/referencias.js +1 -1
  217. package/lib/estudio/visao/visao.swift +97 -0
  218. package/lib/estudio/visao.js +60 -0
  219. package/lib/local/cerebro.json +192 -6
  220. package/lib/local/motor.js +5 -2
  221. package/lib/mcp.js +105 -7
  222. package/lib/nuvem.js +11 -1
  223. package/lib/outra-pasta.js +1 -1
  224. package/lib/passagem.js +50 -0
  225. package/lib/perigo.js +29 -12
  226. package/lib/protecao.js +134 -0
  227. package/lib/sandbox.js +11 -4
  228. package/lib/titulo-conversa.js +46 -0
  229. package/lib/tools.js +3 -0
  230. package/lib/ui.js +1 -1
  231. package/package.json +3 -2
  232. package/skills/editar-meu-video/SKILL.md +6 -2
  233. package/skills/editar-video/SKILL.md +113 -0
  234. package/studio/pessoa.py +52 -0
  235. package/voz/primo_voz/app.py +43 -4
  236. package/voz/primo_voz/chat.html +17 -6
  237. package/voz/primo_voz/painel_dados.py +134 -0
@@ -0,0 +1,167 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR"><head><meta charset="UTF-8"/><title>k3d · tela (vídeo ou imagem da pessoa num aparelho 3D)</title></head>
3
+ <body>
4
+ <!--
5
+ Kit 3D (d): um aparelho de verdade em 3D (notebook ou celular, com espessura, teclado e borda chanfrada) com o
6
+ vídeo ou a imagem da pessoa na tela. Abre parado de frente (parece o vídeo normal), gira um pouco na palavra
7
+ combinada para mostrar o corpo do aparelho e termina parado.
8
+ HONESTIDADE: a tela é um plano chapado com o vídeo colado. O aparelho tem volume; a pessoa na tela não ganha
9
+ volume nenhum quando gira (de lado, a imagem só fica mais estreita). Diga isso na entrega. Guia: references/3d.md.
10
+ Vídeo: o <video id="k3dt-midia"> abaixo. Ponha em data-media-start o segundo do corte em que a cena começa (o
11
+ "de" dela no projeto.json) para a boca bater com a voz, e em data-duration a duração da cena. Para uma imagem,
12
+ troque o <video> por <img id="k3dt-midia" src="assets/foto.jpg" alt=""/> (mesmo id).
13
+ Para usar: copie para compositions/cenas/<nome>.html, troque "k3d_tela" (template, raiz e ID) e o prefixo
14
+ "k3dt-", mude os PARÂMETROS e ligue no projeto.json em "cenas_proprias".
15
+ -->
16
+ <template id="k3d_tela-template">
17
+ <style>
18
+ @font-face{font-family:Montserrat;src:url("assets/fontes/Montserrat.ttf") format("truetype");font-weight:100 900;font-display:block}
19
+ #root{position:absolute;inset:0;overflow:hidden;font-family:Montserrat}
20
+ #k3dt-palco{position:absolute;inset:0;opacity:0}
21
+ #k3dt-tela{position:absolute;left:0;top:0;width:100%;height:100%;display:block}
22
+ #k3dt-rotulos{position:absolute;inset:0}
23
+ #k3dt-midia{position:absolute;left:0;top:0;width:320px;height:568px;object-fit:cover;opacity:0}
24
+ </style>
25
+ <div id="root" data-composition-id="k3d_tela" data-width="1080" data-height="1920" data-duration="5">
26
+ <video id="k3dt-midia" src="assets/cut.mp4" muted playsinline data-start="0" data-duration="5" data-media-start="0" data-track-index="0"></video>
27
+ <div id="k3dt-palco"><canvas id="k3dt-tela" width="1080" height="1920"></canvas><div id="k3dt-rotulos"></div></div>
28
+ </div>
29
+ <script>
30
+ (function () {
31
+ const ID = "k3d_tela";
32
+ // ------------------------------------------------------------------ PARÂMETROS (troque aqui)
33
+ const PARAM = {
34
+ aparelho: "notebook", // "notebook" ou "celular"
35
+ encaixe: "conter", // "conter" (a imagem inteira, com fundo borrado) ou "cobrir" (preenche e corta)
36
+ foco: 0.35, // "cobrir": que altura da imagem fica na tela (0 = topo, 0.5 = meio)
37
+ corCorpo: null, // cor do aparelho (null = base do estilo)
38
+ gira: { palavra: "computador", padrao: 2.4 }, // quando o giro começa
39
+ duracaoGiro: 1.2,
40
+ cameraInicio: { azim: 0, elev: null }, // de frente para a tela (elev null = na altura da tela)
41
+ cameraFim: { azim: 38, elev: 26 }, // onde para: mostra a espessura e o corpo do aparelho
42
+ rotulo: null, // {texto: "roda aqui", palavra: "roda"}: rótulo preso ao aparelho
43
+ fundo: "papel", // "papel", "#rrggbb" ou null (transparente)
44
+ area: null, // [x0, y0, x1, y1] em px onde fica o 3D; null = zona segura
45
+ recorte: true, // com area: o 3D só aparece dentro dela (janela de cantos redondos)
46
+ sombras: true, // sombra das luzes (false deixa o render mais leve; a sombra de contato fica)
47
+ entrada: 0.2,
48
+ saida: 0.2,
49
+ };
50
+ // ------------------------------------------------------------------ dados do build.py (padrões para abrir sozinha)
51
+ const C = Object.assign({ palavras: [], duracao: 5, largura: 1080, altura: 1920, seguro: [140, 230, 940, 1530], rosto: null,
52
+ cores: { papel: "#fffdfd", linha: "#e6ddf8", base: "#c7b7ef", destaque: "#665080", tinta: "#352c40", verde: "#2e9e5b", vermelho: "#e5484d" } },
53
+ (window.__cenas || {})[ID] || {});
54
+ const DUR = C.duracao;
55
+
56
+ async function construir(K, P) {
57
+ const THREE = K.THREE;
58
+ const corpo = PARAM.corCorpo || C.cores.base;
59
+ const lados = "#" + new THREE.Color(corpo).multiplyScalar(0.78).getHexString();
60
+ P.luzes({ chave: [4, 8, 7], alvo: [0, 0.8, 0], area: 5 });
61
+ P.chao({ tamanho: 22 });
62
+ const el = document.getElementById("k3dt-midia");
63
+ if (el.tagName === "IMG" && !(el.complete && el.naturalWidth)) await new Promise((ok) => { el.onload = ok; el.onerror = ok; });
64
+ const notebook = PARAM.aparelho !== "celular";
65
+ const tamTela = notebook ? [2.72, 1.7] : [0.92, 1.96];
66
+ const px = notebook ? [1280, 800] : [540, 1150];
67
+ const midia = P.texturaDeMidia(el, { largura: px[0], altura: px[1], foco: PARAM.foco, encaixe: PARAM.encaixe });
68
+ const telaMat = new THREE.MeshBasicMaterial({ map: midia.textura, toneMapped: false });
69
+ const aparelho = new THREE.Group();
70
+ let centroTela, normalTela, telaMalha;
71
+ if (notebook) {
72
+ // base com teclado e trackpad
73
+ const base = P.placa({ largura: 3.0, altura: 0.11, profundidade: 2.0, raio: 0.14, chanfro: 0.03, cor: corpo, lados });
74
+ aparelho.add(base);
75
+ const teclado = P.placa({ largura: 2.6, altura: 0.012, profundidade: 0.95, raio: 0.05, chanfro: 0.004, cor: C.cores.tinta });
76
+ teclado.position.set(0, 0.105, -0.38);
77
+ aparelho.add(teclado);
78
+ const teclas = new THREE.InstancedMesh(new THREE.BoxGeometry(0.16, 0.02, 0.16), P.material("#f4f1fb", { rugosidade: 0.7, verniz: 0 }), 13 * 5);
79
+ const m = new THREE.Matrix4();
80
+ let n = 0;
81
+ for (let r = 0; r < 5; r++) for (let c = 0; c < 13; c++) { m.makeTranslation(-1.14 + c * 0.19, 0.122, -0.76 + r * 0.19); teclas.setMatrixAt(n++, m); }
82
+ teclas.castShadow = true;
83
+ aparelho.add(teclas);
84
+ const pad = P.placa({ largura: 0.95, altura: 0.006, profundidade: 0.55, raio: 0.06, chanfro: 0.002, cor: lados });
85
+ pad.position.set(0, 0.108, 0.55);
86
+ aparelho.add(pad);
87
+ // tampa articulada no fundo da base, aberta a 108 graus, com a tela na face de dentro
88
+ const dobra = new THREE.Group();
89
+ dobra.position.set(0, 0.11, -1.0);
90
+ dobra.rotation.x = -THREE.MathUtils.degToRad(108);
91
+ const tampa = P.placa({ largura: 3.0, altura: 0.07, profundidade: 2.0, raio: 0.14, chanfro: 0.025, cor: corpo, lados });
92
+ tampa.position.set(0, 0, 1.0);
93
+ dobra.add(tampa);
94
+ const moldura = P.placa({ largura: 2.9, altura: 0.004, profundidade: 1.9, raio: 0.1, chanfro: 0.001, cor: C.cores.tinta });
95
+ moldura.position.set(0, -0.003, 1.0);
96
+ dobra.add(moldura);
97
+ const tela = new THREE.Mesh(new THREE.PlaneGeometry(tamTela[0], tamTela[1]), telaMat);
98
+ tela.rotation.x = Math.PI / 2; // de frente para fora da tampa
99
+ tela.position.set(0, -0.006, 1.02);
100
+ dobra.add(tela);
101
+ aparelho.add(dobra);
102
+ telaMalha = tela;
103
+ aparelho.updateMatrixWorld(true);
104
+ centroTela = tela.getWorldPosition(new THREE.Vector3());
105
+ normalTela = new THREE.Vector3(0, 0, 1).applyQuaternion(tela.getWorldQuaternion(new THREE.Quaternion()));
106
+ } else {
107
+ // celular em pé: corpo com espessura e a tela na frente
108
+ const corpoCel = P.placa({ largura: 1.02, altura: 0.1, profundidade: 2.1, raio: 0.16, chanfro: 0.03, cor: corpo, lados });
109
+ const frente = P.placa({ largura: 0.98, altura: 0.004, profundidade: 2.06, raio: 0.14, chanfro: 0.001, cor: C.cores.tinta });
110
+ frente.position.y = 0.1;
111
+ const tela = new THREE.Mesh(new THREE.PlaneGeometry(tamTela[0], tamTela[1]), telaMat);
112
+ tela.rotation.x = -Math.PI / 2;
113
+ tela.position.y = 0.106;
114
+ const deitado = new THREE.Group();
115
+ deitado.add(corpoCel, frente, tela);
116
+ deitado.rotation.x = Math.PI / 2; // fica em pé, tela para a câmera
117
+ deitado.position.set(0, 1.05, 0);
118
+ aparelho.add(deitado);
119
+ telaMalha = tela;
120
+ aparelho.updateMatrixWorld(true);
121
+ centroTela = tela.getWorldPosition(new THREE.Vector3());
122
+ normalTela = new THREE.Vector3(0, 0, 1).applyQuaternion(tela.getWorldQuaternion(new THREE.Quaternion()));
123
+ }
124
+ P.cena.add(aparelho);
125
+ P.solido(aparelho, PARAM.aparelho);
126
+ const tam = new THREE.Box3().setFromObject(aparelho).getSize(new THREE.Vector3());
127
+ P.sombraDeContato({ largura: tam.x, profundidade: notebook ? 2.1 : 0.3, forca: 0.5 }).colocar(0, notebook ? 0 : 0.05, 0);
128
+ // câmera: começa perpendicular à tela (parece o vídeo chapado) e termina num 3/4 que mostra o corpo
129
+ const elevTela = THREE.MathUtils.radToDeg(Math.asin(K.lim(normalTela.y, -1, 1)));
130
+ const ini = { alvo: centroTela.toArray(), azim: PARAM.cameraInicio.azim, elev: PARAM.cameraInicio.elev == null ? elevTela : PARAM.cameraInicio.elev };
131
+ ini.dist = P.distanciaQueCabe(new THREE.Box3().setFromObject(telaMalha), ini, 1.1);
132
+ const caixaTudo = new THREE.Box3().setFromObject(aparelho);
133
+ const fim = { alvo: caixaTudo.getCenter(new THREE.Vector3()).toArray(), azim: PARAM.cameraFim.azim, elev: PARAM.cameraFim.elev };
134
+ fim.dist = P.distanciaQueCabe(caixaTudo, fim, 1.08);
135
+ const tGira = K.momento(C, PARAM.gira, 2.4);
136
+ const rot = PARAM.rotulo ? P.rotulos([{ texto: PARAM.rotulo.texto, lado: "cima" }]) : null;
137
+ const tRot = PARAM.rotulo ? K.momento(C, PARAM.rotulo, tGira) : 0;
138
+ return (t) => {
139
+ P.orbita(K.misturaPose(ini, fim, K.trecho(t, tGira, PARAM.duracaoGiro)));
140
+ if (rot) rot.atualizar([{ ponto: [0, tam.y + 0.05, notebook ? -1.0 : 0], opacidade: K.trecho(t, tRot, 0.25) }]);
141
+ };
142
+ }
143
+
144
+ // ------------------------------------------------------------------ ligação com o HyperFrames (não precisa mexer)
145
+ const palco = document.getElementById("k3dt-palco");
146
+ const tl = gsap.timeline({ paused: true });
147
+ const relogio = { t: 0 };
148
+ let desenhar = null;
149
+ tl.fromTo(relogio, { t: 0 }, { t: DUR, duration: DUR, ease: "none", onUpdate: () => desenhar && desenhar(relogio.t) }, 0);
150
+ if (PARAM.entrada > 0) tl.fromTo(palco, { opacity: 0 }, { opacity: 1, duration: PARAM.entrada, ease: "power1.out" }, 0);
151
+ else tl.set(palco, { opacity: 1 }, 0);
152
+ if (PARAM.saida > 0) tl.fromTo(palco, { opacity: 1 }, { opacity: 0, duration: PARAM.saida, ease: "power1.in", immediateRender: false }, Math.max(0, DUR - PARAM.saida));
153
+ window.__timelines["k3d_tela"] = tl;
154
+ window.addEventListener("hf-seek", () => { if (desenhar) desenhar(relogio.t); });
155
+ const src = typeof __hfCompositionSrc === "string" ? __hfCompositionSrc : "";
156
+ const RAIZ = src.includes("/compositions/") ? src.slice(0, src.lastIndexOf("/compositions/") + 1) : document.baseURI;
157
+ const fundo = PARAM.fundo === "papel" ? C.cores.papel : PARAM.fundo;
158
+ (window.__hf = window.__hf || {}).buildReady = window.__hf.buildReady || {};
159
+ window.__hf.buildReady[ID] = import(new URL("compositions/cenas/3d/motor-three.js", RAIZ).href)
160
+ .then((K) => K.iniciar({ id: ID, C, raiz: RAIZ, canvas: document.getElementById("k3dt-tela"), camada: document.getElementById("k3dt-rotulos"),
161
+ fundo, area: PARAM.area, recorte: PARAM.area && PARAM.recorte ? PARAM.area : null, fov: 30, sombras: PARAM.sombras, construir: (P) => construir(K, P) }))
162
+ .then((d) => { desenhar = d; desenhar(relogio.t); })
163
+ .catch((e) => console.error(`[cena 3D ${ID}] não carreguei o motor 3D: ${e && e.message ? e.message : e}`));
164
+ })();
165
+ </script>
166
+ </template>
167
+ </body></html>
@@ -0,0 +1,124 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR"><head><meta charset="UTF-8"/><title>k3d · volume (texto ou objeto em volume girando)</title></head>
3
+ <body>
4
+ <!--
5
+ Kit 3D (c): uma palavra (ou um objeto) em volume de verdade, parada no começo, que gira um pouco na palavra
6
+ combinada para mostrar a espessura e as laterais, com luz de estúdio e sombra no chão, e termina parada.
7
+ Serve quando o volume é a mensagem (o objeto tem corpo, o texto "salta" do plano). Querer só que "pareça caro"
8
+ não justifica: aí 2D serve melhor. Guia: references/3d.md da skill.
9
+ Para usar: copie para compositions/cenas/<nome>.html, troque "k3d_volume" (template, raiz e ID) e o prefixo
10
+ "k3dv-", mude os PARÂMETROS abaixo e ligue no projeto.json em "cenas_proprias".
11
+ -->
12
+ <template id="k3d_volume-template">
13
+ <style>
14
+ @font-face{font-family:Montserrat;src:url("assets/fontes/Montserrat.ttf") format("truetype");font-weight:100 900;font-display:block}
15
+ #root{position:absolute;inset:0;overflow:hidden;font-family:Montserrat}
16
+ #k3dv-palco{position:absolute;inset:0;opacity:0}
17
+ #k3dv-tela{position:absolute;left:0;top:0;width:100%;height:100%;display:block}
18
+ #k3dv-rotulos{position:absolute;inset:0}
19
+ </style>
20
+ <div id="root" data-composition-id="k3d_volume" data-width="1080" data-height="1920" data-duration="5">
21
+ <div id="k3dv-palco"><canvas id="k3dv-tela" width="1080" height="1920"></canvas><div id="k3dv-rotulos"></div></div>
22
+ </div>
23
+ <script>
24
+ (function () {
25
+ const ID = "k3d_volume";
26
+ // ------------------------------------------------------------------ PARÂMETROS (troque aqui)
27
+ const PARAM = {
28
+ objeto: "texto", // "texto" (letras em volume), "caixa" (sólido simples) ou "modelo" (.glb/.gltf da pessoa)
29
+ texto: "UMA VEZ\nSÓ", // objeto "texto": o que vira volume (\n quebra a linha; acento serve)
30
+ modelo: "assets/modelo.glb", // objeto "modelo": arquivo liberado para uso, a partir da pasta do projeto
31
+ cor: null, // cor da frente (null = destaque do estilo)
32
+ corLados: null, // cor das laterais e da espessura (null = tinta do estilo): é o que aparece no giro
33
+ espessura: 0.34, // profundidade das letras, em alturas de letra
34
+ gira: { palavra: "uma", padrao: 0.8 }, // quando o giro começa: palavra da fala (ou segundos da cena)
35
+ duracaoGiro: 1.3, // segundos do giro (preso à fala: começa na palavra)
36
+ anguloInicio: -34, // graus: como a peça abre, parada (já mostrando um pouco da lateral)
37
+ anguloFim: 18, // graus: onde termina parada (o ângulo que mais mostra o volume)
38
+ elevacao: 13, // graus da câmera acima do chão
39
+ fundo: "papel", // "papel" (cor do estilo), "#rrggbb" ou null (transparente: o vídeo aparece por baixo)
40
+ area: null, // [x0, y0, x1, y1] em px onde a peça fica; null = zona segura
41
+ recorte: true, // com area: o 3D só aparece dentro dela (janela de cantos redondos)
42
+ rotulo: null, // {texto: "tem espessura", palavra: "vez"}: um rótulo preso à lateral da peça
43
+ sombras: true, // sombra das luzes (false deixa o render mais leve; a sombra de contato fica)
44
+ entrada: 0.2, // segundos para a cena surgir (0 = corte seco)
45
+ saida: 0.2, // segundos para sumir no fim
46
+ };
47
+ // ------------------------------------------------------------------ dados do build.py (padrões para abrir sozinha)
48
+ const C = Object.assign({ palavras: [], duracao: 5, largura: 1080, altura: 1920, seguro: [140, 230, 940, 1530], rosto: null,
49
+ cores: { papel: "#fffdfd", linha: "#e6ddf8", base: "#c7b7ef", destaque: "#665080", tinta: "#352c40", verde: "#2e9e5b", vermelho: "#e5484d" } },
50
+ (window.__cenas || {})[ID] || {});
51
+ const DUR = C.duracao;
52
+
53
+ // o que acontece em cada t (s da cena): nada aqui depende do quadro anterior
54
+ async function construir(K, P) {
55
+ const THREE = K.THREE;
56
+ const cor = PARAM.cor || C.cores.destaque, lados = PARAM.corLados || C.cores.tinta;
57
+ P.luzes({ chave: [3.2, 7, 6.5], alvo: [0, 0.5, 0], area: 6 });
58
+ P.chao({ tamanho: 22 });
59
+ let peca, noTempo = null;
60
+ if (PARAM.objeto === "modelo") {
61
+ const m = await P.carregarModelo(PARAM.modelo, { altura: 1.6 });
62
+ peca = m.objeto;
63
+ noTempo = m.noTempo; // animação que vem dentro do modelo, posta no tempo da cena
64
+ }
65
+ else if (PARAM.objeto === "caixa") peca = P.caixa({ largura: 1.6, altura: 1.6, profundidade: 1.6, raio: 0.18, chanfro: 0.06, cor, lados });
66
+ else peca = await P.textoEmVolume(PARAM.texto, { altura: 1, espessura: PARAM.espessura, cor, lados });
67
+ const giro = new THREE.Group();
68
+ giro.add(peca);
69
+ P.cena.add(giro);
70
+ P.solido(peca, "a peça");
71
+ const tam = new THREE.Box3().setFromObject(peca).getSize(new THREE.Vector3());
72
+ const sombra = P.sombraDeContato({ largura: tam.x, profundidade: Math.max(tam.z, 0.35), forca: 0.5 });
73
+ // a câmera fica numa distância em que a peça cabe inteira em todos os ângulos do giro
74
+ const caixaGiro = new THREE.Box3();
75
+ for (let k = 0; k <= 8; k++) {
76
+ giro.rotation.y = THREE.MathUtils.degToRad(K.mistura(PARAM.anguloInicio, PARAM.anguloFim, k / 8));
77
+ giro.updateMatrixWorld(true);
78
+ caixaGiro.union(new THREE.Box3().setFromObject(peca));
79
+ }
80
+ const alvo = caixaGiro.getCenter(new THREE.Vector3()).toArray();
81
+ const dist = P.distanciaQueCabe(caixaGiro, { alvo, azim: 0, elev: PARAM.elevacao }, 1.0);
82
+ const tGira = K.momento(C, PARAM.gira, 0.8);
83
+ const rot = PARAM.rotulo ? P.rotulos([{ texto: PARAM.rotulo.texto, lado: "dir" }]) : null;
84
+ const tRot = PARAM.rotulo ? K.momento(C, PARAM.rotulo, tGira + PARAM.duracaoGiro) : 0;
85
+ const lateral = new THREE.Vector3();
86
+ return (t) => {
87
+ const k = K.trecho(t, tGira, PARAM.duracaoGiro);
88
+ const ang = THREE.MathUtils.degToRad(K.mistura(PARAM.anguloInicio, PARAM.anguloFim, k));
89
+ giro.rotation.y = ang;
90
+ if (noTempo) noTempo(t);
91
+ sombra.colocar(0, 0, 0, 1, ang);
92
+ P.orbita({ alvo, dist, azim: 0, elev: PARAM.elevacao });
93
+ if (rot) {
94
+ lateral.set(tam.x / 2, tam.y * 0.55, 0).applyAxisAngle(new THREE.Vector3(0, 1, 0), ang);
95
+ rot.atualizar([{ ponto: lateral, opacidade: K.trecho(t, tRot, 0.25) }]);
96
+ }
97
+ };
98
+ }
99
+
100
+ // ------------------------------------------------------------------ ligação com o HyperFrames (não precisa mexer)
101
+ const palco = document.getElementById("k3dv-palco");
102
+ const tl = gsap.timeline({ paused: true });
103
+ const relogio = { t: 0 };
104
+ let desenhar = null;
105
+ // o relógio da cena é esta timeline: o HyperFrames posiciona o tempo e o 3D é desenhado para aquele t
106
+ tl.fromTo(relogio, { t: 0 }, { t: DUR, duration: DUR, ease: "none", onUpdate: () => desenhar && desenhar(relogio.t) }, 0);
107
+ if (PARAM.entrada > 0) tl.fromTo(palco, { opacity: 0 }, { opacity: 1, duration: PARAM.entrada, ease: "power1.out" }, 0);
108
+ else tl.set(palco, { opacity: 1 }, 0);
109
+ if (PARAM.saida > 0) tl.fromTo(palco, { opacity: 1 }, { opacity: 0, duration: PARAM.saida, ease: "power1.in", immediateRender: false }, Math.max(0, DUR - PARAM.saida));
110
+ window.__timelines["k3d_volume"] = tl;
111
+ window.addEventListener("hf-seek", () => { if (desenhar) desenhar(relogio.t); });
112
+ const src = typeof __hfCompositionSrc === "string" ? __hfCompositionSrc : "";
113
+ const RAIZ = src.includes("/compositions/") ? src.slice(0, src.lastIndexOf("/compositions/") + 1) : document.baseURI;
114
+ const fundo = PARAM.fundo === "papel" ? C.cores.papel : PARAM.fundo;
115
+ (window.__hf = window.__hf || {}).buildReady = window.__hf.buildReady || {};
116
+ window.__hf.buildReady[ID] = import(new URL("compositions/cenas/3d/motor-three.js", RAIZ).href)
117
+ .then((K) => K.iniciar({ id: ID, C, raiz: RAIZ, canvas: document.getElementById("k3dv-tela"), camada: document.getElementById("k3dv-rotulos"),
118
+ fundo, area: PARAM.area, recorte: PARAM.area && PARAM.recorte ? PARAM.area : null, fov: 28, sombras: PARAM.sombras, construir: (P) => construir(K, P) }))
119
+ .then((d) => { desenhar = d; desenhar(relogio.t); })
120
+ .catch((e) => console.error(`[cena 3D ${ID}] não carreguei o motor 3D: ${e && e.message ? e.message : e}`));
121
+ })();
122
+ </script>
123
+ </template>
124
+ </body></html>