from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from math import pi
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from panda3d.core import Point3, KeyboardButton, CollisionBox, CollisionSphere, CollisionNode, CollisionTraverser, \
    CollisionHandlerQueue

from panda3d.core import  Vec3

class MyApp(ShowBase):
    def __init__(self):
        #-------------ЧТобы мы могли с движком
        ShowBase.__init__(self) #Python брат , мы теперь иммед доступ к Panda3D
        #----------------------------------------------------------------------
        self.level = self.loader.loadModel("models/environment") #loader.loadModel Загружают
        #fbx,obj,stl
        self.level.reparentTo(self.render) #Отрисовка
                            #x    y    z
        self.level.setScale(0.25,0.25,0.25) #менят размер модели ( можно использовать инвертироварование моделей)
        self.level.setPos(0,0,0) #изменяет позицию
        #from direct.actor.Actor import Actor
        self.PandaActor = Actor("models/panda-model",
                                {"walk":"models/panda-walk4"} )
        self.PandaActor.setScale(0.01,0.01,0.01)
        self.PandaActor.reparentTo(self.render)
        self.PandaActor.loop("walk")
        #from direct.interval.IntervalGlobal import Sequence
        #from panda3d.core import Point3\


        #                                         повремя     до чего x y z  startPos старт
        posInterval1 = self.PandaActor.posInterval(13,Point3(0,-10,0),
                                                   startPos=Point3(0,10,0))
        posInterval2 = self.PandaActor.posInterval(13, Point3(0,10,0),
                                                   startPos=Point3(0,-10,0))
                                        #ПЕРЕДАЕМ ПОРЯДОК
        #self.PandaChekPoint = Sequence(posInterval1,posInterval2, name="PadaCheck")
        #self.PandaChekPoint.loop()
        # Define a procedure to move the camera.
        #self.taskMgr.add(self.spinCameraTask, "Panda")
        #self.taskMgr.add(self.PandaMove, "PandaMove")


        #УПРАВЛЕНИЕ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        self.PandaActor.setPos(0,-30,100)
        self.x = 0
        self.y = -30
        self.z = 100
        self.keyMap = {
            "up"  : False,
            "down" : False,
            "left" : False,
            "right" : False,
            "space" : False
            ###########
            #для пробела space
        }

        self.accept('w',self.updateKey,["up",True])
        self.accept('w-up',self.updateKey, ["up",False])
        self.accept("s", self.updateKey, ["down", True])
        self.accept("s-up", self.updateKey, ["down", False])
        self.accept('a', self.updateKey, ["left", True])
        self.accept('a-up', self.updateKey, ["left", False])
        self.accept('d', self.updateKey, ["right", True])
        self.accept('d-up', self.updateKey, ["right", False])

        ##########
        # добавляем для пробела
        self.accept('space', self.updateKey, ["space", True])
        self.accept('space-up', self.updateKey, ["space", False])



        self.taskMgr.add(self.update, "update")

        self.camera.setPos(self.PandaActor.getX(), self.PandaActor.getY()-15, self.PandaActor.getZ()+10)
        self.camera.lookAt(self.PandaActor)

        #self.taskMgr.add(self.lalala, "update")

############################################################################################
        #Колизия - соприосновения
        #Сфера
                                   #х y z радиус
        cs = CollisionSphere(0, 0, 150, 500)
        box = CollisionBox(20, 20, 20, 500)
        cnodepath2 = self.PandaActor.attachNewNode(CollisionNode('Oleg'))
        cnodepath = self.PandaActor.attachNewNode(CollisionNode('Egor'))

        cnodepath2.node().addSolid(box)  # колизия добавляет в панду бокс

        cnodepath2.show()


        cnodepath.node().addSolid(cs) #колизия добавляет в панду сферу
        cnodepath.show()
###############################################################################################
        #Обработка столкновений
        levelCollider = self.level.attachNewNode(CollisionNode('LevelCollider')) #невидимая коробка для панды
        levelCollider.node().addSolid(CollisionBox((-500, -500, 0), (500, 500, 10))) #раземр коробочки (типо растянули)

        levelCollider.show()

        #Включим обработчик столкновения
        self.cTrav = CollisionTraverser() #обработчик столкновений - проверяет, сталкивается ли панда с чем-то
        self.queue = CollisionHandlerQueue() #сюда записываются столкноения, которые будут обнаружены ударом

        self.cTrav.addCollider(cnodepath, self.queue) #доавбляем нашу панду в обработчик, чтобы игра проверила стокновение

        cnodepath.node().setIntoCollideMask(0) #0 - кто толкает, 1 - кто ждет толчка

        cnodepath.node().setFromCollideMask(1)

        levelCollider.node().setIntoCollideMask(1) #коллизия уровня ждет столкновения, он терпила!

        self.IsGround = False #мы не на земеле

###############!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        self.taskMgr.add(self.checkCollision, "Col")

        self.train = self.level.attachNewNode(CollisionNode('Train'))
        self.train.node().addSolid(CollisionBox((-20, -20, 0), (50, 50, 200)))  # раземр коробочки (типо растянули)

        self.train.show()

        self.train.setPos(0, -1000, 0)

        #task manager - функция
        self.taskMgr.add(self.TrainMove, "train")

    #функция, которая будет двигать поезд на панду
    def TrainMove(self, task):
        fps = task.time
        self.train.setPos(self.train.getPos() + Vec3(0, 1*fps/2, 0))
        # если у = 50, то возвращаете поезд в начальную точку
        # self.train.getPos().у - тут ваш у
        if self.train.getPos().y > 50:
            self.train.setPos(0, -1000, 0)

        return Task.cont

    def checkCollision(self,task):

        fps = task.time
        if self.IsGround == True:
            print("Типо стоит")
            print("Тут типо нет действия падения")
            print("Типо прыгать будет")
        else:
            print("Типо падает")
            print("Тут типо он чето меняет !!!!")
            self.PandaActor.setPos(self.PandaActor.getPos() + Vec3(0, 0, -0.1 * fps))
        self.cTrav.traverse(self.render)

        print(self.queue)
        for entry in self.queue.getEntries():
            name = entry.getIntoNodePath().getName()
            if name == "LevelCollider":
                self.IsGround= True #Стоклнулся дал переменной правду
                print("Типо если столкнулись , то типо меняет Isground на True")
                print("Панда стоклнулся с уровнем")

        return  task.cont

    #########################################################################################################

    def updateKey(self,key,status):
            self.keyMap[key] = status
    def update(self,task):
            fps = task.time
            if self.keyMap["up"]:
                self.PandaActor.setPos(self.PandaActor.getPos() + Vec3(0,-0.1 * fps, 0))
            if self.keyMap["down"]:
                self.PandaActor.setPos(self.PandaActor.getPos() + Vec3(0,0.1 * fps, 0))
            if self.keyMap["left"]:
                self.PandaActor.setPos(self.PandaActor.getPos() + Vec3(-0.1*fps, 0, 0))
            if self.keyMap["right"]:
                self.PandaActor.setPos(self.PandaActor.getPos() + Vec3(0.1*fps,0, 0))
            ##########################
            #добавим и сюда спасе (и сохране) координата (0, 0, любое число больше 10)
            #self.IsGround меняем

            return task.cont
        #задача это написать функцию в которой мы будем "прикреплены" к панде
    def lalala(self, task):
            self.camera.setPos(self.PandaActor.getX(), self.PandaActor.getY() - 15, self.PandaActor.getZ() + 10)
            self.camera.lookAt(self.PandaActor)
            return Task.cont

        #Дальше оформляйте на другие кнопки
    def test(self):
            self.x = self.x + 0.1
            self.PandaActor.setPos(self.x,self.y,self.z)
            #SetPos
            #Сделать управление на все кнопки
            print("Cобытие клавиша нажата W")


    def PandaMove(self,task):
            speed = task.time  * 6.0
            self.PandaActor.setPos(0,-speed,0)
            return  Task.cont
    def spinCameraTask(self, task):
            angleDegrees = task.time * 6.0
            angleRadians = angleDegrees * (pi / 180.0)
            self.camera.setHpr(angleDegrees, 0, 0)
            return task.cont



app = MyApp()
app.run()