kingkont 0.20.35 → 0.20.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.20.35",
3
+ "version": "0.20.37",
4
4
  "description": "KingKont \u00b7 Chatium \u2014 \u043d\u043e\u0434-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0446\u0435\u043d \u0441 AI-\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438/\u0432\u0438\u0434\u0435\u043e/\u0433\u043e\u043b\u043e\u0441/SFX/\u043c\u0443\u0437\u044b\u043a\u0430/\u0442\u0435\u043a\u0441\u0442)",
5
5
  "main": "main.js",
6
6
  "bin": {
package/renderer/board.js CHANGED
@@ -3379,6 +3379,23 @@ async function selectBoard(board) {
3379
3379
  // openRepliquesFor(board.name).catch(e => console.warn('replicas open failed', e));
3380
3380
  // }
3381
3381
  localStorage.setItem(`lastBoard:${state.filmHandle.name}`, JSON.stringify({ kind: board.kind, name: board.name }));
3382
+ // Web: обновить hash чтобы юзер мог расшарить ссылку на конкретную сцену.
3383
+ // Юзер: «когда я открываю сцену — меняй хеш». Формат:
3384
+ // #template=PROJECT&board=ИмяСцены (view-only / template)
3385
+ // #project=PROJECT&board=ИмяСцены (edit mode)
3386
+ // #project=PROJECT&kind=character&board=Анна (персонаж/локация)
3387
+ // history.replaceState — чтобы не засирать history-стек на каждом switch.
3388
+ if (window.__KINGKONT_WEB__ && state.cloudProjectId) {
3389
+ const isTpl = /^#template=/.test(location.hash || '');
3390
+ const prefix = isTpl ? 'template' : 'project';
3391
+ const params = [`${prefix}=${state.cloudProjectId}`];
3392
+ if (board.kind && board.kind !== 'episode') params.push(`kind=${board.kind}`);
3393
+ params.push(`board=${encodeURIComponent(board.name)}`);
3394
+ const newHash = '#' + params.join('&');
3395
+ if (location.hash !== newHash) {
3396
+ history.replaceState(null, '', location.pathname + location.search + newHash);
3397
+ }
3398
+ }
3382
3399
  await refreshSidebar();
3383
3400
  await renderCanvas();
3384
3401
  // Сбрасываем кэш URL клипов и декодированных AudioBuffer от прошлой доски
@@ -1666,11 +1666,19 @@ async function pasteClipboardNodes() {
1666
1666
 
1667
1667
  // Если paste идёт в ту же доску, где копировали — кладём рядом с оригиналами
1668
1668
  // (oldX + offset, oldY + offset). При cross-board — переносим bbox в видимую область.
1669
+ // ВАЖНО: scrollLeft/Top — координаты в frame-системе (включая canvas-pad-x/y),
1670
+ // а ноды живут в canvas-content-coord. Конвертация:
1671
+ // canvas-x = (scrollLeft - padX) / zoom
1672
+ // Раньше тут было `scrollLeft / zoom + 80 - minX` — без вычета padding,
1673
+ // и cross-board paste улетал примерно на (padX/zoom, padY/zoom) ≈ (2000, 1500)
1674
+ // в правую/нижнюю невидимую часть canvas'а. Юзер: «вставка попадает в
1675
+ // невидимую область».
1669
1676
  const sameBoard = state.clipboardSourceBoardKey === state.currentBoard.key;
1677
+ const _pad = (typeof _getFramePadding === 'function') ? _getFramePadding() : { padX: 0, padY: 0 };
1670
1678
  const baseX = sameBoard ? offset
1671
- : (canvasWrap.scrollLeft / state.zoom + 80 - minX);
1679
+ : ((canvasWrap.scrollLeft - _pad.padX) / state.zoom + 80 - minX);
1672
1680
  const baseY = sameBoard ? offset
1673
- : (canvasWrap.scrollTop / state.zoom + 80 - minY);
1681
+ : ((canvasWrap.scrollTop - _pad.padY) / state.zoom + 80 - minY);
1674
1682
 
1675
1683
  for (const item of state.clipboard) {
1676
1684
  const oldNode = item.node;
@@ -1779,8 +1779,11 @@ async function replicaToBoard(charInfo, replica, statusEl) {
1779
1779
  type: 'audio',
1780
1780
  name: slug,
1781
1781
  file,
1782
- x: canvasWrap.scrollLeft / state.zoom + 80,
1783
- y: canvasWrap.scrollTop / state.zoom + 80,
1782
+ // Конвертация frame-coord → canvas-content-coord: вычитаем padX/padY.
1783
+ // Без этого нода с реплики персонажа улетает в невидимую правую/нижнюю
1784
+ // часть canvas'а (≈ padX, padY смещение).
1785
+ x: (canvasWrap.scrollLeft - ((typeof _getFramePadding === 'function' ? _getFramePadding().padX : 0))) / state.zoom + 80,
1786
+ y: (canvasWrap.scrollTop - ((typeof _getFramePadding === 'function' ? _getFramePadding().padY : 0))) / state.zoom + 80,
1784
1787
  generated: {
1785
1788
  kind: 'audio', prompt: replica.text, rawPrompt: replica.text,
1786
1789
  model: 'eleven_v3', voiceId: charInfo.voice, voiceName: charInfo.voiceName || '',