reckfellENGINE

Мышь: viewport и локальные координаты

Преобразовать клик и различить Relative и ScreenRelative.

На этой странице

Сначала определите систему координат. Позиция курсора в окне, точка внутри viewport, мировая позиция 2D и локальная позиция объекта — разные величины. Совпадение чисел в неподвижной сцене не делает их взаимозаменяемыми.

Откуда брать точку

КонтекстЗначение
Событие мыши в обработчике EntityInputEventMouseButton.Position или InputEventMouseMotion.Position — координаты события в viewport.
GUI-обработчик ControlСобытие может быть уже преобразовано в локальную систему Control. Не применяйте преобразование viewport повторно.
Текущее состояние viewportGetViewport().GetMousePosition() — текущая позиция, а не обязательно позиция прежнего события.
Объект 2DПреобразуйте точку из того же viewport в локальную систему объекта.
Выбор объекта 3DПостройте луч камерой по точке viewport; одной координаты глубины из мыши не получить.

GlobalPosition события мыши не является мировой позицией вашего Entity2D. Для клика по конкретному событию сохраняйте его Position; повторный опрос позже может вернуть уже другую позицию.

Viewport → локальная точка 2D

Файл ниже учитывает преобразование объекта и canvas. Используйте его для точки того же viewport, где находится цель; цель должна быть подключена к корректному дереву, а преобразование — обратимо.

C#
using Reckfell;

public static class PointerCoordinates
{
    // point must be in the same viewport as target.
    public static Vector2 ToLocal(CanvasItem target, Vector2 point) =>
        target.GetGlobalTransformWithCanvas().AffineInverse() * point;
}

В _UnhandledInput() проверьте InputEventMouseButton с Pressed=true и ButtonIndex=MouseButton.Left, затем передайте его Position в PointerCoordinates.ToLocal(this, position) для своей Entity2D. Вы получите точку в её локальных координатах. _UnhandledInput() подходит, если интерфейс должен получить возможность обработать клик раньше игровой логики; маршрут события.

Проверенный пример: canvas имеет масштаб 2 и сдвиг (100, 50), объект — позицию (10, 20) и масштаб 2. Точка viewport (168, 154) преобразуется в локальную (12, 16). Простое вычитание позиции объекта здесь дало бы неправильный результат.

Не используйте матрицу одного viewport для событий другого. Если событие уже преобразовано в локальные координаты Control, повторное применение этой функции тоже даст неверную точку.

Перемещение мыши и поворот камеры

Relative — приращение, которое может масштабироваться при преобразовании события. ScreenRelative сохраняет экранное приращение; ScreenVelocity — экранную скорость. Это не абсолютная позиция.

В проверке двукратное преобразование события изменило Relative с (3, 4) на (6, 8), а ScreenRelative осталось (3, 4). Для чувствительности обзора, не зависящей от масштаба отображения, используйте подходящее экранное приращение. Не умножайте уже полученное смещение за событие на delta второй раз как скорость; для стика, задающего угловую скорость, расчёт другой.

В режиме захвата не рассчитывайте поворот по абсолютной позиции курсора. Обрабатывайте относительное движение и предусмотрите освобождение курсора для меню. Сам захват курсора зависит от оконной системы и не проверяется синтетическим событием.

Для 3D

Используйте Camera3D.ProjectRayOrigin() и ProjectRayNormal(), затем физический запрос с нужной длиной и маской. Камера и точка должны относиться к одному viewport. Готовый пример: выбор объекта лучом.

Выполнены преобразования при масштабе canvas и объекта, различение Position/GlobalPosition, Relative/ScreenRelative. Живой курсор, захват ОС, GUI-маршрутизация, вложенные viewport, Camera2D и экспорт этим тестом не оценивались.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.