fix(09): studs не растягиваются при scale-drag примитива
All checks were successful
All checks were successful
При scale-гизмо mesh.scaling тянул faceUV → studs превращались в полосы. Фикс: во время drag прячем studs-текстуру (плоский цвет), в dragEnd меш пересоздаётся с правильным faceUV. _recreateMesh для studs пересоздаёт материал заново (свежий тайлинг + восстановление текстуры). GizmoController: + onDrag (live) колбэк для scale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f6828aad2c
commit
ea80ec3aa6
@ -1332,6 +1332,9 @@ export class BabylonScene {
|
|||||||
|
|
||||||
// При окончании drag — синхронизируем
|
// При окончании drag — синхронизируем
|
||||||
this._gizmo.setOnDragEnd(() => this._onGizmoDragEnd());
|
this._gizmo.setOnDragEnd(() => this._onGizmoDragEnd());
|
||||||
|
// Во время scale-drag — live-обновление тайлинга studs (кружки одного
|
||||||
|
// размера, не растягиваются пока тянешь гизмо).
|
||||||
|
this._gizmo.setOnDrag((mode) => { if (mode === 'scale') this._onGizmoScaleDrag(); });
|
||||||
|
|
||||||
// Привязка гизмо к выделенному
|
// Привязка гизмо к выделенному
|
||||||
this.selection.setOnSelectionChange((sel) => this._updateGizmoForSelection(sel));
|
this.selection.setOnSelectionChange((sel) => this._updateGizmoForSelection(sel));
|
||||||
@ -3547,6 +3550,25 @@ export class BabylonScene {
|
|||||||
* Гизмо манипулировал объектом — синхронизируем через SelectionManager.
|
* Гизмо манипулировал объектом — синхронизируем через SelectionManager.
|
||||||
* Тип операции (move/rotate/scale) определяется по режиму гизмо.
|
* Тип операции (move/rotate/scale) определяется по режиму гизмо.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Во время scale-drag studs-примитива: текстура (faceUV) растягивается
|
||||||
|
* вместе с mesh.scaling и кружки превращаются в полосы. Чтобы не показывать
|
||||||
|
* это — временно прячем diffuse/bump-текстуру (плоский цвет). В dragEnd меш
|
||||||
|
* пересоздаётся с правильным faceUV и текстура возвращается.
|
||||||
|
*/
|
||||||
|
_onGizmoScaleDrag() {
|
||||||
|
if (!this.selection) return;
|
||||||
|
const sel = this.selection.getSelection?.();
|
||||||
|
if (!sel || sel.type !== 'primitive' || sel.material !== 'studs') return;
|
||||||
|
const mat = sel.mesh?.material;
|
||||||
|
if (mat && mat.diffuseTexture && !mat._studsHidden) {
|
||||||
|
mat._studsStash = { diffuse: mat.diffuseTexture, bump: mat.bumpTexture };
|
||||||
|
mat.diffuseTexture = null;
|
||||||
|
mat.bumpTexture = null;
|
||||||
|
mat._studsHidden = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onGizmoDragEnd() {
|
_onGizmoDragEnd() {
|
||||||
if (!this.selection || !this._gizmo) return;
|
if (!this.selection || !this._gizmo) return;
|
||||||
const sel = this.selection.getSelection();
|
const sel = this.selection.getSelection();
|
||||||
|
|||||||
@ -38,6 +38,7 @@ export class GizmoController {
|
|||||||
|
|
||||||
setOnDragEnd(cb) { this._onDragEnd = cb; }
|
setOnDragEnd(cb) { this._onDragEnd = cb; }
|
||||||
setOnDragStart(cb) { this._onDragStart = cb; }
|
setOnDragStart(cb) { this._onDragStart = cb; }
|
||||||
|
setOnDrag(cb) { this._onDrag = cb; }
|
||||||
|
|
||||||
/** Главный метод — переключить режим. */
|
/** Главный метод — переключить режим. */
|
||||||
setMode(mode) {
|
setMode(mode) {
|
||||||
@ -88,6 +89,13 @@ export class GizmoController {
|
|||||||
gizmo.onDragStartObservable.add(() => {
|
gizmo.onDragStartObservable.add(() => {
|
||||||
if (this._onDragStart) this._onDragStart();
|
if (this._onDragStart) this._onDragStart();
|
||||||
});
|
});
|
||||||
|
// onDrag (в процессе перетаскивания) — для live-обновления (напр. тайлинг
|
||||||
|
// studs, чтобы кружки не растягивались пока тянешь scale-гизмо).
|
||||||
|
if (gizmo.onDragObservable) {
|
||||||
|
gizmo.onDragObservable.add(() => {
|
||||||
|
if (this._onDrag) this._onDrag(mode);
|
||||||
|
});
|
||||||
|
}
|
||||||
gizmo.onDragEndObservable.add(() => {
|
gizmo.onDragEndObservable.add(() => {
|
||||||
if (this._onDragEnd) this._onDragEnd();
|
if (this._onDragEnd) this._onDragEnd();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -843,7 +843,15 @@ export class PrimitiveManager {
|
|||||||
const newMesh = this._createMeshForType(typeDef, data.id, data.sx, data.sy, data.sz, data.material, data.studDensity);
|
const newMesh = this._createMeshForType(typeDef, data.id, data.sx, data.sy, data.sz, data.material, data.studDensity);
|
||||||
newMesh.position = oldPos;
|
newMesh.position = oldPos;
|
||||||
if (oldRot) newMesh.rotation = oldRot;
|
if (oldRot) newMesh.rotation = oldRot;
|
||||||
|
// studs — материал пересоздаём заново (свежий faceUV/тайлинг + текстура
|
||||||
|
// могла быть временно спрятана во время scale-drag). Иначе переносим старый.
|
||||||
|
if (data.material === 'studs') {
|
||||||
|
newMesh._studsDims = { type: data.type, sx: data.sx, sy: data.sy, sz: data.sz, density: data.studDensity };
|
||||||
|
this._applyMaterial(newMesh, typeDef, data.color, data.material);
|
||||||
|
try { oldMat?.dispose(); } catch (e) { /* ignore */ }
|
||||||
|
} else {
|
||||||
newMesh.material = oldMat;
|
newMesh.material = oldMat;
|
||||||
|
}
|
||||||
newMesh.isPickable = true;
|
newMesh.isPickable = true;
|
||||||
newMesh.metadata = { ...oldMesh.metadata };
|
newMesh.metadata = { ...oldMesh.metadata };
|
||||||
newMesh.setEnabled(data.visible);
|
newMesh.setEnabled(data.visible);
|
||||||
@ -853,24 +861,8 @@ export class PrimitiveManager {
|
|||||||
catch (e) { /* ignore */ }
|
catch (e) { /* ignore */ }
|
||||||
|
|
||||||
data.mesh = newMesh;
|
data.mesh = newMesh;
|
||||||
newMesh._studsDims = { type: data.type, sx: data.sx, sy: data.sy, sz: data.sz, density: data.studDensity };
|
// _studsDims и материал studs уже выставлены выше (через _applyMaterial
|
||||||
// studs-материал: пересчитать тайлинг под новый размер меша.
|
// на новом меше с правильным faceUV/тайлингом). Для не-studs ничего не надо.
|
||||||
// Куб уже пересоздан с новым faceUV (тайлинг в геометрии) — uScale=1.
|
|
||||||
// Для остальных форм пересчитываем uScale/vScale по размеру.
|
|
||||||
if (data.material === 'studs' && oldMat && oldMat.diffuseTexture) {
|
|
||||||
if (data.type === 'cube' || data.type === 'trigger') {
|
|
||||||
oldMat.diffuseTexture.uScale = oldMat.diffuseTexture.vScale = 1;
|
|
||||||
if (oldMat.bumpTexture) oldMat.bumpTexture.uScale = oldMat.bumpTexture.vScale = 1;
|
|
||||||
} else {
|
|
||||||
const tile = _studsTiling(data.type, data.sx, data.sy, data.sz, data.studDensity);
|
|
||||||
oldMat.diffuseTexture.uScale = tile.u;
|
|
||||||
oldMat.diffuseTexture.vScale = tile.v;
|
|
||||||
if (oldMat.bumpTexture) {
|
|
||||||
oldMat.bumpTexture.uScale = tile.u;
|
|
||||||
oldMat.bumpTexture.vScale = tile.v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Удалить инстанс. */
|
/** Удалить инстанс. */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user