fix(player): клик по 3D-табличкам в third-person (свободный курсор)
_handlePlayClick пикал билборд из ЦЕНТРА экрана (w/2,h/2) — верно только при pointer-lock. В third курсор свободен, юзер кликает мышью НЕ в центре → pick промахивался, кнопки табличек не нажимались (Ферма 1981 и др). Фикс: onMouseDown передаёт реальные canvas-координаты клика в _handlePlayClick(clickX,clickY); при locked — центр, иначе — точка клика. Добавлен console.log [billboard] для диагностики попадания. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fe23d099cd
commit
7b869c83bd
@ -2183,8 +2183,12 @@ export class BabylonScene {
|
|||||||
const onMouseDown = (e) => {
|
const onMouseDown = (e) => {
|
||||||
if (this._isPlaying) {
|
if (this._isPlaying) {
|
||||||
// В Play-режиме ЛКМ — клик игрока в forward-направлении.
|
// В Play-режиме ЛКМ — клик игрока в forward-направлении.
|
||||||
// Pointer Lock — курсор всё равно в центре экрана.
|
// При pointer-lock курсор в центре; в third (свободный курсор)
|
||||||
if (e.button === 0) this._handlePlayClick();
|
// передаём реальные координаты клика для pick по табличкам.
|
||||||
|
if (e.button === 0) {
|
||||||
|
const r = canvas.getBoundingClientRect();
|
||||||
|
this._handlePlayClick(e.clientX - r.left, e.clientY - r.top);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Обновляем pointer координаты для raycast и Gizmo
|
// Обновляем pointer координаты для raycast и Gizmo
|
||||||
@ -2913,7 +2917,7 @@ export class BabylonScene {
|
|||||||
* - в self-обработчики скриптов (routeEvent с target)
|
* - в self-обработчики скриптов (routeEvent с target)
|
||||||
* - в глобальные обработчики (game.onClick) с event.target
|
* - в глобальные обработчики (game.onClick) с event.target
|
||||||
*/
|
*/
|
||||||
_handlePlayClick() {
|
_handlePlayClick(clickX, clickY) {
|
||||||
if (!this._isPlaying) return;
|
if (!this._isPlaying) return;
|
||||||
|
|
||||||
// Мультиплеер-выстрел: если у сцены есть mpSync, шлём 'shoot' серверу.
|
// Мультиплеер-выстрел: если у сцены есть mpSync, шлём 'shoot' серверу.
|
||||||
@ -2936,12 +2940,17 @@ export class BabylonScene {
|
|||||||
if (!this.gameRuntime) return;
|
if (!this.gameRuntime) return;
|
||||||
|
|
||||||
// === Задача 01: клик по КНОПКЕ 3D-таблички (billboard) ===
|
// === Задача 01: клик по КНОПКЕ 3D-таблички (billboard) ===
|
||||||
// Пикаем из центра экрана (как _pickFromCenter — в Play обычно
|
// При pointer-lock (first/shift-lock) курсор в центре экрана → пикаем
|
||||||
// pointer-lock). Если попали в кнопку таблички → fireClick и выходим.
|
// из центра. В third курсор СВОБОДНЫЙ → пикаем по реальным координатам
|
||||||
|
// клика (clickX/clickY переданы из onMouseDown). Без этого клик по
|
||||||
|
// табличке мышью в third промахивался — кнопки не нажимались.
|
||||||
if (this.billboardUiManager && this.primitiveManager) {
|
if (this.billboardUiManager && this.primitiveManager) {
|
||||||
|
const locked = (document.pointerLockElement === this.canvas);
|
||||||
const w = this.engine?.getRenderWidth?.() || this.canvas.width;
|
const w = this.engine?.getRenderWidth?.() || this.canvas.width;
|
||||||
const h = this.engine?.getRenderHeight?.() || this.canvas.height;
|
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
|
m && m.metadata && m.metadata.primitiveId != null
|
||||||
&& this.primitiveManager.instances.get(m.metadata.primitiveId)?.type === 'billboard');
|
&& this.primitiveManager.instances.get(m.metadata.primitiveId)?.type === 'billboard');
|
||||||
if (bpick && bpick.hit && bpick.pickedMesh) {
|
if (bpick && bpick.hit && bpick.pickedMesh) {
|
||||||
@ -2949,10 +2958,16 @@ export class BabylonScene {
|
|||||||
const uv = bpick.getTextureCoordinates ? bpick.getTextureCoordinates() : null;
|
const uv = bpick.getTextureCoordinates ? bpick.getTextureCoordinates() : null;
|
||||||
if (bdata && uv) {
|
if (bdata && uv) {
|
||||||
const buttonId = this.billboardUiManager.pickButtonAt(bdata, uv.x, uv.y);
|
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) {
|
if (buttonId) {
|
||||||
this.billboardUiManager.fireClick(bdata, buttonId);
|
this.billboardUiManager.fireClick(bdata, buttonId);
|
||||||
return; // клик по табличке обработан
|
return; // клик по табличке обработан
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[billboard] попал в табличку id='
|
||||||
|
+ bpick.pickedMesh.metadata.primitiveId + ' но нет UV');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user