fix(studio): групповые манипуляции папки в реальном времени (не телепорт)
Дельта пивота применялась только в dragEnd → объекты телепортировались в конце. Теперь _onFolderGizmoDrag применяет инкрементальную дельту на каждом тике (setOnDrag) — движение/вращение/масштаб группы видно в процессе, как у одиночных объектов. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8b887e866a
commit
c7b5f3645d
@ -1367,7 +1367,12 @@ export class BabylonScene {
|
||||
this._gizmo.setOnDragEnd(() => this._onGizmoDragEnd());
|
||||
// Во время scale-drag — live-обновление тайлинга studs (кружки одного
|
||||
// размера, не растягиваются пока тянешь гизмо).
|
||||
this._gizmo.setOnDrag((mode) => { if (mode === 'scale') this._onGizmoScaleDrag(); });
|
||||
this._gizmo.setOnDrag((mode) => {
|
||||
if (mode === 'scale') this._onGizmoScaleDrag();
|
||||
// Групповая папка — применяем дельту в реальном времени (видно движение).
|
||||
const sel = this.selection?.getSelection?.();
|
||||
if (sel && sel.type === 'folder') this._onFolderGizmoDrag(mode);
|
||||
});
|
||||
|
||||
// Привязка гизмо к выделенному
|
||||
this.selection.setOnSelectionChange((sel) => this._updateGizmoForSelection(sel));
|
||||
@ -3756,36 +3761,59 @@ export class BabylonScene {
|
||||
pivot.scaling = new Vector3(1, 1, 1);
|
||||
this._folderPivot = pivot;
|
||||
this._folderPivotId = folderId;
|
||||
// Запоминаем стартовое состояние пивота для вычисления дельты в dragEnd.
|
||||
this._folderPivotStart = {
|
||||
pos: { x: center.x, y: center.y, z: center.z },
|
||||
// «Последнее применённое» состояние пивота — для инкрементальной
|
||||
// дельты в реальном времени (_onFolderGizmoDrag).
|
||||
this._folderPivotLast = {
|
||||
x: center.x, y: center.y, z: center.z,
|
||||
ry: 0, scale: 1,
|
||||
center: { x: center.x, y: center.y, z: center.z },
|
||||
};
|
||||
} catch (e) { console.warn('[folderGizmo] attach failed', e); }
|
||||
}
|
||||
|
||||
/** Применить трансформацию пивота к объектам папки (вызывается на dragEnd). */
|
||||
_applyFolderGizmo(mode) {
|
||||
/**
|
||||
* Инкрементально применить движение/поворот/масштаб пивота к объектам папки
|
||||
* ПРЯМО ВО ВРЕМЯ drag (чтобы было видно перемещение, а не телепорт в конце).
|
||||
*/
|
||||
_onFolderGizmoDrag(mode) {
|
||||
const pivot = this._folderPivot;
|
||||
const fid = this._folderPivotId;
|
||||
const start = this._folderPivotStart;
|
||||
if (!pivot || fid == null || !start || !this.folderManager) return;
|
||||
const last = this._folderPivotLast;
|
||||
if (!pivot || fid == null || !last || !this.folderManager) return;
|
||||
if (mode === 'move') {
|
||||
const dx = pivot.position.x - start.pos.x;
|
||||
const dy = pivot.position.y - start.pos.y;
|
||||
const dz = pivot.position.z - start.pos.z;
|
||||
if (dx || dy || dz) this.folderManager.moveFolderBy(fid, dx, dy, dz);
|
||||
const dx = pivot.position.x - last.x;
|
||||
const dy = pivot.position.y - last.y;
|
||||
const dz = pivot.position.z - last.z;
|
||||
if (dx || dy || dz) {
|
||||
this.folderManager.moveFolderBy(fid, dx, dy, dz);
|
||||
last.x = pivot.position.x; last.y = pivot.position.y; last.z = pivot.position.z;
|
||||
last.center.x += dx; last.center.y += dy; last.center.z += dz;
|
||||
}
|
||||
} else if (mode === 'rotate') {
|
||||
const ry = pivot.rotation.y;
|
||||
if (Math.abs(ry) > 0.0001) this.folderManager.rotateFolderY(fid, ry, start.center);
|
||||
const dRy = pivot.rotation.y - last.ry;
|
||||
if (Math.abs(dRy) > 0.0001) {
|
||||
this.folderManager.rotateFolderY(fid, dRy, last.center);
|
||||
last.ry = pivot.rotation.y;
|
||||
}
|
||||
} else if (mode === 'scale') {
|
||||
const f = (pivot.scaling.x + pivot.scaling.y + pivot.scaling.z) / 3;
|
||||
if (Math.abs(f - 1) > 0.001) this.folderManager.scaleFolder(fid, f, start.center);
|
||||
const cur = (pivot.scaling.x + pivot.scaling.y + pivot.scaling.z) / 3;
|
||||
const factor = last.scale !== 0 ? cur / last.scale : 1;
|
||||
if (Math.abs(factor - 1) > 0.001) {
|
||||
this.folderManager.scaleFolder(fid, factor, last.center);
|
||||
last.scale = cur;
|
||||
}
|
||||
}
|
||||
// Пересоздаём пивот в новом центре (сброс дельты для следующего drag).
|
||||
}
|
||||
|
||||
/** dragEnd: дельта уже применена в _onFolderGizmoDrag — пересоздаём пивот. */
|
||||
_applyFolderGizmo(mode) {
|
||||
const fid = this._folderPivotId;
|
||||
if (fid == null || !this.folderManager) return;
|
||||
// На всякий случай добираем остаток дельты (если drag был очень коротким).
|
||||
this._onFolderGizmoDrag(mode);
|
||||
// Пересоздаём пивот в новом центре (сброс для следующего drag).
|
||||
const g = this.folderManager.getFolderObjects(fid);
|
||||
this._attachFolderGizmo(fid, g.center);
|
||||
// Переустановить gizmo на новый пивот + обновить selection.center.
|
||||
const sel = this.selection?.getSelection?.();
|
||||
if (sel && sel.type === 'folder') { sel.center = g.center; }
|
||||
if (this._gizmo && this._folderPivot) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user