feat: ���� 3D-�������-��������� � ����� + dev JWT-������ #9

Merged
min merged 14 commits from feat/arrow-pointer into main 2026-05-30 19:41:40 +00:00
Showing only changes of commit 7b869c83bd - Show all commits

View File

@ -2183,8 +2183,12 @@ export class BabylonScene {
const onMouseDown = (e) => {
if (this._isPlaying) {
// В Play-режиме ЛКМ — клик игрока в forward-направлении.
// Pointer Lock — курсор всё равно в центре экрана.
if (e.button === 0) this._handlePlayClick();
// При pointer-lock курсор в центре; в third (свободный курсор)
// передаём реальные координаты клика для pick по табличкам.
if (e.button === 0) {
const r = canvas.getBoundingClientRect();
this._handlePlayClick(e.clientX - r.left, e.clientY - r.top);
}
return;
}
// Обновляем pointer координаты для raycast и Gizmo
@ -2913,7 +2917,7 @@ export class BabylonScene {
* - в self-обработчики скриптов (routeEvent с target)
* - в глобальные обработчики (game.onClick) с event.target
*/
_handlePlayClick() {
_handlePlayClick(clickX, clickY) {
if (!this._isPlaying) return;
// Мультиплеер-выстрел: если у сцены есть mpSync, шлём 'shoot' серверу.
@ -2936,12 +2940,17 @@ export class BabylonScene {
if (!this.gameRuntime) return;
// === Задача 01: клик по КНОПКЕ 3D-таблички (billboard) ===
// Пикаем из центра экрана (как _pickFromCenter — в Play обычно
// pointer-lock). Если попали в кнопку таблички → fireClick и выходим.
// При pointer-lock (first/shift-lock) курсор в центре экрана → пикаем
// из центра. В third курсор СВОБОДНЫЙ → пикаем по реальным координатам
// клика (clickX/clickY переданы из onMouseDown). Без этого клик по
// табличке мышью в third промахивался — кнопки не нажимались.
if (this.billboardUiManager && this.primitiveManager) {
const locked = (document.pointerLockElement === this.canvas);
const w = this.engine?.getRenderWidth?.() || this.canvas.width;
const h = this.engine?.getRenderHeight?.() || this.canvas.height;
const bpick = this.scene.pick(w / 2, h / 2, (m) =>
const px = locked ? w / 2 : (Number.isFinite(clickX) ? clickX : w / 2);
const py = locked ? h / 2 : (Number.isFinite(clickY) ? clickY : h / 2);
const bpick = this.scene.pick(px, py, (m) =>
m && m.metadata && m.metadata.primitiveId != null
&& this.primitiveManager.instances.get(m.metadata.primitiveId)?.type === 'billboard');
if (bpick && bpick.hit && bpick.pickedMesh) {
@ -2949,10 +2958,16 @@ export class BabylonScene {
const uv = bpick.getTextureCoordinates ? bpick.getTextureCoordinates() : null;
if (bdata && uv) {
const buttonId = this.billboardUiManager.pickButtonAt(bdata, uv.x, uv.y);
console.log('[billboard] клик id=' + bpick.pickedMesh.metadata.primitiveId
+ ' uv=(' + uv.x.toFixed(2) + ',' + uv.y.toFixed(2) + ') buttonId=' + buttonId
+ ' locked=' + locked);
if (buttonId) {
this.billboardUiManager.fireClick(bdata, buttonId);
return; // клик по табличке обработан
}
} else {
console.log('[billboard] попал в табличку id='
+ bpick.pickedMesh.metadata.primitiveId + ' но нет UV');
}
}
}