feat(09): Studs материал + окрашиваемые блоки + лего-сет #20
@ -1332,6 +1332,9 @@ export class BabylonScene {
|
||||
|
||||
// При окончании drag — синхронизируем
|
||||
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));
|
||||
@ -3547,6 +3550,25 @@ export class BabylonScene {
|
||||
* Гизмо манипулировал объектом — синхронизируем через SelectionManager.
|
||||
* Тип операции (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() {
|
||||
if (!this.selection || !this._gizmo) return;
|
||||
const sel = this.selection.getSelection();
|
||||
|
||||
@ -38,6 +38,7 @@ export class GizmoController {
|
||||
|
||||
setOnDragEnd(cb) { this._onDragEnd = cb; }
|
||||
setOnDragStart(cb) { this._onDragStart = cb; }
|
||||
setOnDrag(cb) { this._onDrag = cb; }
|
||||
|
||||
/** Главный метод — переключить режим. */
|
||||
setMode(mode) {
|
||||
@ -88,6 +89,13 @@ export class GizmoController {
|
||||
gizmo.onDragStartObservable.add(() => {
|
||||
if (this._onDragStart) this._onDragStart();
|
||||
});
|
||||
// onDrag (в процессе перетаскивания) — для live-обновления (напр. тайлинг
|
||||
// studs, чтобы кружки не растягивались пока тянешь scale-гизмо).
|
||||
if (gizmo.onDragObservable) {
|
||||
gizmo.onDragObservable.add(() => {
|
||||
if (this._onDrag) this._onDrag(mode);
|
||||
});
|
||||
}
|
||||
gizmo.onDragEndObservable.add(() => {
|
||||
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);
|
||||
newMesh.position = oldPos;
|
||||
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.isPickable = true;
|
||||
newMesh.metadata = { ...oldMesh.metadata };
|
||||
newMesh.setEnabled(data.visible);
|
||||
@ -853,24 +861,8 @@ export class PrimitiveManager {
|
||||
catch (e) { /* ignore */ }
|
||||
|
||||
data.mesh = newMesh;
|
||||
newMesh._studsDims = { type: data.type, sx: data.sx, sy: data.sy, sz: data.sz, density: data.studDensity };
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// _studsDims и материал studs уже выставлены выше (через _applyMaterial
|
||||
// на новом меше с правильным faceUV/тайлингом). Для не-studs ничего не надо.
|
||||
}
|
||||
|
||||
/** Удалить инстанс. */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user