from direct.showbase.ShowBase import ShowBase
from panda3d.core import Geom, GeomVertexFormat, GeomVertexData, GeomVertexWriter, GeomLines, GeomNode
from panda3d.core import LineSegs, TextNode
from panda3d.core import WindowProperties
from direct.gui.OnscreenText import OnscreenText

from hyperdiamond import HyperDiamond
from data import *

class Panda3dApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        
        #window title
        win_props = WindowProperties()
        win_props.setTitle("Hyper-diamond")
        base.win.requestProperties(win_props)
        
        #initialize model
        self.angle = 5.0
        self.hd = HyperDiamond()
        
        #keyboard control
        self.accept("i",self.keyI)
        self.accept("p",self.keyP)
        
        self.accept("q",self.keyQ)
        self.accept("w",self.keyW)
        self.accept("a",self.keyA)
        self.accept("s",self.keyS)
        self.accept("y",self.keyY)
        self.accept("x",self.keyX)        
        
        #per axes (red, green, blue)
        v3format = GeomVertexFormat.getV3c4()
        vertices = GeomVertexData("per_axes", v3format, Geom.UHStatic)
        vertices.setNumRows (6)
        
        vertex_data = GeomVertexWriter(vertices, "vertex")
        vertex_color = GeomVertexWriter(vertices, "color")
        
        for i in range(1, 4):   
            vertex_data.addData3(0.0, 0.0, 0.0)
            vertex_color.addData4(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)
            vertex_data.addData3(per_axes[i][0], per_axes[i][1], per_axes[i][2])
            vertex_color.addData4(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)            
        
        lines = GeomLines(Geom.UHStatic)  
        lines.addVertices(0,1)
        lines.addVertices(2,3)
        lines.addVertices(4,5)
        lines.closePrimitive()
        
        axes_geom = Geom(vertices)
        axes_geom.addPrimitive(lines)
        
        axes_node = GeomNode("per_axes")
        axes_node.addGeom(axes_geom)
        self.per_axes_path = render.attachNewNode(axes_node)        
        
        #per axes labes
        for i in range(1, 4):
            text = TextNode(axes_labels[i])
            text.setText(axes_labels[i])
            text.setTextColor(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)        
            textNodePath = self.per_axes_path.attachNewNode(text)
            textNodePath.setScale(0.1)
            textNodePath.setPos(per_axes[i][0], per_axes[i][1], per_axes[i][2])
            textNodePath.set_two_sided (True);        
        
        #iso axes (white, red, green, blue)
        v3format = GeomVertexFormat.getV3c4()
        vertices = GeomVertexData("iso_axes", v3format, Geom.UHStatic)
        vertices.setNumRows (8)
        
        vertex_data = GeomVertexWriter(vertices, "vertex")
        vertex_color = GeomVertexWriter(vertices, "color")
        
        for i in range(4):   
            vertex_data.addData3(0.0, 0.0, 0.0)
            vertex_color.addData4(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)
            vertex_data.addData3(iso_axes[i][0], iso_axes[i][1], iso_axes[i][2])
            vertex_color.addData4(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)            
        
        lines = GeomLines(Geom.UHStatic)  
        lines.addVertices(0,1)
        lines.addVertices(2,3)
        lines.addVertices(4,5)
        lines.addVertices(6,7)
        lines.closePrimitive()
        
        axes_geom = Geom(vertices)
        axes_geom.addPrimitive(lines)
        
        axes_node = GeomNode("iso_axes")
        axes_node.addGeom(axes_geom)
        self.iso_axes_path = render.attachNewNode(axes_node)
        self.iso_axes_path.hide()
        
        #iso axes labes
        for i in range(4):
            text = TextNode(axes_labels[i])
            text.setText(axes_labels[i])
            text.setTextColor(axes_colors[i][0], axes_colors[i][1], axes_colors[i][2], 1.0)        
            textNodePath = self.iso_axes_path.attachNewNode(text)
            textNodePath.setScale(0.1)
            textNodePath.setPos(iso_axes[i][0], iso_axes[i][1], iso_axes[i][2])
            textNodePath.set_two_sided (True);
        
        #set linesegs
        self.ls = LineSegs()
        self.ls.setThickness(2)
        
        #tesseract 1 (yellow)
        self.ls.setColor(0.8, 0.8, 0.2, 1.0)
        for i in range(32):
            move = self.hd.lines[i][0]
            draw = self.hd.lines[i][1]
            self.ls.moveTo(move[0], move[1], move[2])
            self.ls.drawTo(draw[0], draw[1], draw[2])
        
        #tesseract 1 (cyan)
        self.ls.setColor(0.2, 0.8, 0.8, 1.0)
        for i in range(32, 64):
            move = self.hd.lines[i][0]
            draw = self.hd.lines[i][1]
            self.ls.moveTo(move[0], move[1], move[2])
            self.ls.drawTo(draw[0], draw[1], draw[2])
            
        #tesseract 1 (magenta)
        self.ls.setColor(0.8, 0.2, 0.8, 1.0)
        for i in range(64, 96):
            move = self.hd.lines[i][0]
            draw = self.hd.lines[i][1]
            self.ls.moveTo(move[0], move[1], move[2])
            self.ls.drawTo(draw[0], draw[1], draw[2])         
        
        node = self.ls.create()
        node_path = render.attachNewNode(node)
        
        base.cam.setPos(0.0, -4.0, 0.0)
    
        self.projection_label = OnscreenText(text="perspective",
                                             pos = (-1.05, 0.9),
                                             scale = 0.08,
                                             fg = (0.9, 0.9, 0.9, 0.9))       
    
    def keyI(self):
        self.hd.perspective = False
        self.per_axes_path.hide()
        self.iso_axes_path.show()
        self.updateVertices()
        self.projection_label.setText("isometric")
        
    def keyP(self):
        self.hd.perspective = True
        self.iso_axes_path.hide()
        self.per_axes_path.show()
        self.updateVertices()
        self.projection_label.setText("perspective")
        
    def keyQ(self):
        Rotate(0, 1, self.angle)
        self.updateVertices()
    
    def keyW(self):
        Rotate(0, 1, -self.angle)
        self.updateVertices()
        
    def keyA(self):
        Rotate(0, 2, self.angle)
        self.updateVertices()
    
    def keyS(self):
        Rotate(0, 2, -self.angle)
        self.updateVertices()        
    
    def keyY(self):
        Rotate(3, 0, self.angle)
        self.updateVertices()
    
    def keyX(self):
        Rotate(3, 0, -self.angle)
        self.updateVertices()    
    
    def updateVertices(self):
        #update projection to 3D
        self.hd.projectionTo3D()
        
        #update linesegs
        i = 0
        j = 0
        for v in range (self.ls.getNumVertices()):
            vert = self.hd.lines[i][j]
            #print (i, j, vert[0], vert[1], vert[2])
            self.ls.setVertex(v, vert[0], vert[1], vert[2])
            if j == 1:
                i += 1
                j = 0
            else:
                j = 1

app = Panda3dApp()
app.run()