from direct.showbase.ShowBase import ShowBase

# Класс контроллера мышки и клавиатуры
class Controller():
    # Конструктор
    def __init__(self):
        # значение шага перемещения клавиатурой
        self.key_step = 0.2
        # значение шага поворота мышкой
        self.mouse_step = 0.2
        # координаты центра экрана
        self.x_center = base.win.getXSize()//2
        self.y_center = base.win.getYSize()//2
        # перемещаем указатель мышки в центр экрана
        base.win.movePointer(0, self.x_center, self.y_center)
        # отключаем стандартное управление мышкой
        base.disableMouse()

        # устанавливаем текущие значения ориентации камеры
        self.heading = 0
        self.pitch = 0

        # запускаем задачу контроля камеры
        taskMgr.doMethodLater(0.02, self.controlCamera, "camera-task")
        # регистрируем на нажатие клавиши "Esc"
        # событие закрытия приложения
        base.accept("escape", base.userExit)

        # устанавливаем клавиши управления перемещением камеры
        # словарь, хранящий флаги нажатия клавиш
        self.keys = dict()
        # заполняем словарь
        for key in ['a', 'd', 'w', 's', 'q', 'e']:
            # создаём запись в словаре
            self.keys[key] = 0
            # регистрируем событие на нажатие клавиши
            base.accept(key, self.setKey, [key, 1])
            # регистрируем событие на отжатие клавиши
            base.accept(key+'-up', self.setKey, [key, 0])

    # Метод установки шага перемещения
    def setMovingStep(self, step):
        self.key_step = step

    # Метод установки состояния клавиши
    def setKey(self, key, value):
        self.keys[key] = value

    # Метод управления положением и ориентацией камеры
    def controlCamera(self, task):
        # рассчитываем смещения положения камеры по осям X Y Z
        move_x = self.key_step * (self.keys['d'] - self.keys['a'])
        move_y = self.key_step * (self.keys['w'] - self.keys['s'])
        move_z = self.key_step * (self.keys['e'] - self.keys['q'])

        # смещаем позицию камеры относительно предыдущего положения камеры
        base.camera.setPos(base.camera, move_x, move_y, move_z)

        # получаем новое положение курсора мышки
        new_mouse_pos = base.win.getPointer(0)
        new_x = new_mouse_pos.getX()
        new_y = new_mouse_pos.getY()
        # пробуем установить курсор в центр экрана
        if base.win.movePointer(0, self.x_center, self.y_center):
            # рассчитываем поворот камеры по горизонтали
            self.heading = self.heading - (new_x - self.x_center) * self.mouse_step
            # рассчитываем поворот камеры по вертикали
            self.pitch = self.pitch - (new_y - self.y_center) * self.mouse_step
            # устанавливаем новую ориентацию камеры
            base.camera.setHpr(self.heading, self.pitch, 0)

        # сообщаем о необходимости повторного запуска задачи
        return task.again
