From 0e4fa89f40e098317b62fdc4d8eff8c715945daa Mon Sep 17 00:00:00 2001 From: min Date: Fri, 5 Jun 2026 09:20:15 +0300 Subject: [PATCH] =?UTF-8?q?fix(studio):=20=D0=B4=D0=B5=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=20=D0=B4=D0=B2=D0=B5=D1=80=D0=B8=20(=D1=84=D0=B8=D0=BB=D1=91?= =?UTF-8?q?=D0=BD=D0=BA=D0=B8+=D1=80=D1=83=D1=87=D0=BA=D0=B0)=20=D0=B2?= =?UTF-8?q?=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B5=20=D1=81=20=D0=BF=D0=BE=D0=BB=D0=BE?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Декор-части находятся по имени (findOne), их локальное смещение от центра полотна поворачивается вокруг той же петли в place() — теперь филёнки и ручка открываются вместе с дверью, а не висят в проёме. Co-Authored-By: Claude Opus 4.8 --- src/editor/engine/GameplayKits.js | 37 +++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/editor/engine/GameplayKits.js b/src/editor/engine/GameplayKits.js index 915d9c6..8573630 100644 --- a/src/editor/engine/GameplayKits.js +++ b/src/editor/engine/GameplayKits.js @@ -285,18 +285,41 @@ game.self.onTouch(() => { // Скрипт на полотне двери. Филёнки/ручка двигаются вместе как часть полотна? // Нет — они отдельные примитивы, поэтому анимируем только полотно (game.self), // а декор оставляем — на низкой толщине двери смотрится цельно. -const p0 = game.self.position; -const halfW = 1.3; // половина ширины полотна по Z (sz=2.6) -const hingeZ = p0.z - halfW; // петля у левого края +const p0 = game.self.position; // центр полотна (закрытое положение) +const halfW = 1.3; // половина ширины полотна по Z (sz=2.6) +const hingeX = p0.x; +const hingeZ = p0.z - halfW; // петля у левого края let open = false; -let cur = 0, target = 0; // текущий и целевой угол (радианы) -const SPEED = Math.PI; // рад/сек → ~0.5с на 90° +let cur = 0, target = 0; // текущий и целевой угол (радианы) +const SPEED = Math.PI; // рад/сек → ~0.5с на 90° + +// Декор полотна — двигаем вместе с дверью. Запоминаем их СМЕЩЕНИЕ относительно +// центра полотна (в закрытом виде), чтобы вращать вокруг той же петли. +const decorNames = ['Филёнка верх', 'Филёнка низ', 'Ручка']; +const decor = []; +for (const nm of decorNames) { + const o = game.scene.findOne(nm); + if (o && o.position) { + decor.push({ obj: o, dx: o.position.x - p0.x, dy: o.position.y - p0.y, dz: o.position.z - p0.z }); + } +} + function place(angle) { - const cx = p0.x + Math.sin(angle) * halfW; - const cz = hingeZ + Math.cos(angle) * halfW; + const s = Math.sin(angle), c = Math.cos(angle); + // Полотно: его центр на дуге вокруг петли. + const cx = hingeX + s * halfW; + const cz = hingeZ + c * halfW; game.self.move(cx, p0.y, cz); game.self.rotate(angle); + // Декор: позиция центра полотна + повёрнутое локальное смещение. + for (const d of decor) { + const rx = d.dx * c - d.dz * s; // поворот смещения вокруг Y + const rz = d.dx * s + d.dz * c; + d.obj.move(cx + rx, p0.y + d.dy, cz + rz); + if (d.obj.rotate) d.obj.rotate(angle); + } } + // Один постоянный тик плавно ведёт cur → target. game.onTick((dt) => { if (cur === target) return;