Completed
Push — master ( d03520...f1f8b6 )
by Matthew
01:00
created

framework.game.GameManager.render()   B

Complexity

Conditions 2

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 2
dl 0
loc 36
rs 8.8571
1
import math
2
3
from ed2d import window
4
from ed2d import sysevents
5
from ed2d.events import Events
6
from ed2d import context
7
from ed2d import timing
8
from ed2d import files
9
from ed2d import shaders
10
from ed2d.opengl import gl
11
from ed2d.opengl import pgl
12
from gem import vector
13
from gem import matrix
14
from ed2d import mesh
15
from ed2d import text
16
from ed2d import camera
17
from ed2d.scenegraph import SceneGraph
18
from ed2d.assets import objloader
19
from ed2d import cursor
20
from ed2d import view
21
22
class Viewport(object):
23
    '''Basic data container to allow changing the viewport to simpler.'''
24
    def __init__(self, name, camera):
25
        self.name = name
26
        self.camera = camera
27
        self.width = 0
28
        self.height = 0
29
        self.x = 0
30
        self.y = 0
31
        self.screenSize = None
32
33
    def set_rect(self, x, y, width, height):
34
        self.width = width
35
        self.height = height
36
        self.x = x
37
        self.y = y
38
39
    def make_current(self):
40
        if self.camera:
41
            if self.camera.get_mode() == camera.MODE_PERSPECTIVE:
42
                self.camera.set_projection(75.0, float(self.width) / float(self.height), 1e-6, 1e27)
43
            else:
44
                self.camera.set_projection(0.0, self.width, self.height, 0.0, -1.0, 1.0)
45
            self.camera.make_current()
46
47
        gl.glViewport(self.x, self.screenSize[1]-self.y-self.height, self.width, self.height)
48
49
class ViewportManager(object):
50
    '''Viewport Manager is for handling multiple split views '''
51
    def __init__(self):
52
        self.view = view.View()
53
        self.viewports = []
54
        self.screenSize = (0, 0)
55
    
56
    def update_screen(self, width, height):
57
        self.screenSize = (width, height)
58
        for vp in self.viewports:
59
            vp.screenSize = self.screenSize
60
61
    def create_viewport(self, name, camera):
62
        camera.set_view(self.view)
63
        vp = Viewport(name, camera)
64
        vp.screenSize = self.screenSize
65
        self.viewports.append(vp)
66
        return vp
67
68
class GameManager(object):
69
    ''' Entry point into the game, and manages the game in general '''
70
    def __init__(self):
71
72
        self.width = 1920
73
        self.height = 1080
74
        self.title = "ed2d"
75
        self.running = False
76
77
        self.fpsTimer = timing.FpsCounter()
78
        self.fpsEstimate = 0
79
80
        self.sysEvents = sysevents.SystemEvents()
81
        self.window = window.Window(self.title, self.width, self.height, window.WindowedMode)
82
        self.context = context.Context(3, 3, 2)
83
        self.context.window = self.window
84
85
        Events.add_listener(self.process_event)
86
87
        self.keys = []
88
89
        # Mouse Information
90
        self.mousePos = [0.0, 0.0]
91
        self.mouseButtons = []
92
        self.mouseRelX = 0
93
        self.mouseRelY = 0
94
        self.mousePosX = 0
95
        self.mousePosY = 0
96
        cursor.set_relative_mode(False)
97
        cursor.show_cursor()
98
99
        gl.init()
100
        major = pgl.glGetInteger(gl.GL_MAJOR_VERSION)
101
        minor = pgl.glGetInteger(gl.GL_MINOR_VERSION)
102
        print('OpenGL Version: {}.{}'.format(major, minor))
103
104
        gl.glViewport(0, 0, self.width, self.height)
105
106
        # For CSG to work properly
107
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
108
        gl.glEnable(gl.GL_DEPTH_TEST)
109
        gl.glEnable(gl.GL_CULL_FACE)
110
        gl.glEnable(gl.GL_MULTISAMPLE)
111
112
        gl.glClearColor(0.0, 0.0, 0.4, 0.0)
113
114
        vsPath = files.resolve_path('data', 'shaders', 'main2.vs')
115
        fsPath = files.resolve_path('data', 'shaders', 'main2.fs')
116
117
        vertex = shaders.VertexShader(vsPath)
118
        fragment = shaders.FragmentShader(fsPath)
119
        self.program = shaders.ShaderProgram(vertex, fragment)
120
        self.program.use()
121
122
        #self.testID1 = self.program.new_uniform(b'perp')
123
        self.testID2 = self.program.new_uniform(b'view')
124
125
        self.vao = pgl.glGenVertexArrays(1)
126
127
        self.scenegraph = SceneGraph()
128
129
        # Creating a object steps:
130
        # Create a mesh object to render
131
        objFL = objloader.OBJ('buildings')
132
        self.meshTest = mesh.Mesh()
133
        self.meshTest.fromData(objFL)
134
        self.meshTest.addProgram(self.program)
135
        self.meshTestID = self.scenegraph.establish(self.meshTest)
136
        self.meshTest.translate(0.0, 0.0, 0.0)
137
138
139
        objBox = objloader.OBJ('box')
140
        self.boxMesh = mesh.Mesh()
141
        self.boxMesh.fromData(objBox)
142
        self.boxMesh.addProgram(self.program)
143
        self.boxMesh.scale(0.25)
144
        self.boxMeshID = self.scenegraph.establish(self.boxMesh)
145
146
147
        self.loadText()
148
149
        self.vpManager = ViewportManager()
150
        self.vpManager.update_screen(self.width, self.height)
151
152
        self.cameraOrtho = camera.Camera(camera.MODE_ORTHOGRAPHIC)
153
        self.cameraOrtho.set_view(self.vpManager.view)
154
        self.cameraOrtho.set_program(self.textProgram)
155
        self.vpFull = Viewport('full', self.cameraOrtho)
156
        self.vpFull.screenSize = (self.width, self.height)
157
        
158
        for i in range(4):
159
            cam = camera.Camera(camera.MODE_PERSPECTIVE)
160
            vp = self.vpManager.create_viewport('sceneview{0}'.format(i), cam)
161
162
            cam.setPosition(vector.Vector(3, data=[0.5, -2.0, 10.0]))
163
            cam.set_program( self.program)
164
165
        halfWidth = int(self.width /2)
166
        halfHeight = int(self.height/2)
167
        
168
        vps = self.vpManager.viewports
169
        vps[0].set_rect(0,         0,          halfWidth, halfHeight)
170
        vps[1].set_rect(0,         halfHeight, halfWidth, halfHeight)
171
        vps[2].set_rect(halfWidth, halfHeight, halfWidth, halfHeight)
172
        vps[3].set_rect(halfWidth, 0,          halfWidth, halfHeight)
173
        self.camera = vps[0].camera
174
175
        self.vpFull.set_rect(0, 0, self.width, self.height)
176
177
        self.model = matrix.Matrix(4)
178
        #self.model = matrix.Matrix(4).translate(vector.Vector(3, data=[4.0, -2.0, -8]))
179
180
181
        glerr = gl.glGetError()
182
        if glerr != 0:
183
            print('GLError:', glerr)
184
185
    def loadText(self):
186
        vsPath = files.resolve_path('data', 'shaders', 'font.vs')
187
        fsPath = files.resolve_path('data', 'shaders', 'font.fs')
188
189
        vertex = shaders.VertexShader(vsPath)
190
        fragment = shaders.FragmentShader(fsPath)
191
        self.textProgram = shaders.ShaderProgram(vertex, fragment)
192
193
        fontPath = files.resolve_path('data', 'SourceCodePro-Regular.ttf')
194
        self.font = text.Font(12, fontPath)
195
        self.text = text.Text(self.textProgram, self.font)
196
197
    def resize(self, width, height):
198
        self.width = width
199
        self.height = height
200
        
201
        self.vpManager.update_screen(self.width, self.height)
202
        self.vpFull.screenSize = (self.width, self.height)
203
204
        halfWidth = int(self.width /2)
205
        halfHeight = int(self.height/2)
206
207
        vps = self.vpManager.viewports
208
        vps[0].set_rect(0,         0,          halfWidth, halfHeight)
209
        vps[1].set_rect(halfWidth, 0,          halfWidth, halfHeight)
210
        vps[2].set_rect(halfWidth, halfHeight, halfWidth, halfHeight)
211
        vps[3].set_rect(0,         halfHeight, halfWidth, halfHeight)
212
        
213
        self.vpFull.set_rect(0, 0, self.width, self.height)
214
215
    def process_event(self, event, data):
216
        if event == 'quit' or event == 'window_close':
217
            self.running = False
218
        elif event == 'window_resized':
219
            winID, x, y = data
220
            self.resize(x, y)
221
        elif event == 'mouse_move':
222
            if cursor.is_relative():
223
                self.mouseRelX, self.mouseRelY = data
224
            else:
225
                self.mousePosX, self.mousePosY = data
226
        elif event == 'key_down':
227
            if data[0] == 'c':
228
                cursor.set_relative_mode(True)
229
            elif data[0] == 'r':
230
                cursor.set_relative_mode(False)
231
                cursor.move_cursor(self.mousePosX, self.mousePosY)
232
            self.keys.append(data[0])
233
            print(self.keys)
234
        elif event == 'key_up':
235
            self.keys.remove(data[0])
236
        elif event == 'mouse_button_down':
237
            self.mouseButtons.append(data[0])
238
            print(self.mouseButtons)
239
        elif event == 'mouse_button_up':
240
            self.mouseButtons.remove(data[0])
241
242
    def keyUpdate(self):
243
244
        moveAmount = 0.5 * self.fpsTimer.tickDelta
245
246
        for key in self.keys:
247
            if key == 'w':
248
                self.camera.move(self.camera.vec_back, moveAmount)
249
250
            elif key == 's':
251
                self.camera.move(self.camera.vec_forward, moveAmount)
252
253
            elif key == 'a':
254
                self.camera.move(self.camera.vec_left, moveAmount)
255
256
            elif key == 'd':
257
                self.camera.move(self.camera.vec_right, moveAmount)
258
259
            elif key == 'q':
260
                self.camera.move(self.camera.vec_up, moveAmount)
261
262
            elif key == 'e':
263
                self.camera.move(self.camera.vec_down, moveAmount)
264
265
            elif key == 'UP':
266
                self.camera.rotate(self.camera.vec_right, moveAmount * 0.05)
267
268
            elif key == 'DOWN':
269
                self.camera.rotate(self.camera.vec_left, moveAmount * 0.05)
270
271
            elif key == 'LEFT':
272
                self.camera.rotate(self.camera.vec_up, moveAmount * 0.05)
273
274
            elif key == 'RIGHT':
275
                self.camera.rotate(self.camera.vec_down, moveAmount * 0.05)
276
277
    def mouseUpdate(self):
278
        
279
        if 1 in self.mouseButtons:
280
            if not cursor.is_relative():
281
                cursor.set_relative_mode(True)
282
            tick = self.fpsTimer.tickDelta
283
            sensitivity = 0.5
284
            if self.mouseRelX != 0:
285
                self.camera.rotate(self.camera.yAxis, math.radians(-self.mouseRelX * sensitivity * tick))
286
287
            if self.mouseRelY != 0:
288
                self.camera.rotate(self.camera.vec_right, math.radians(-self.mouseRelY * sensitivity * tick))
289
290
            self.mouseRelX, self.mouseRelY = 0, 0
291
        else:
292
            if cursor.is_relative():
293
                cursor.set_relative_mode(False)
294
                cursor.move_cursor(self.mousePosX, self.mousePosY)
295
296
    def update(self):
297
        posVec = self.camera.position.vector
298
        self.boxMesh.translate(posVec[0], posVec[1], posVec[2]-2.0)
299
        if not cursor.is_relative():
300
            for vp in self.vpManager.viewports:
301
                w = vp.width
302
                h = vp.height
303
                x = vp.x
304
                y = vp.y
305
                
306
                
307
                if (self.mousePosX >= x and self.mousePosX < x+w and
308
                    self.mousePosY >= y and self.mousePosY < y+h):
309
                    self.camera = vp.camera
310
                    break
311
                
312
            
313
        
314
        self.mouseUpdate()
315
        self.keyUpdate()
316
317
        self.scenegraph.update()
318
319
    def render(self):
320
        # We need this viewport clear the whole screen (I think) 
321
        self.vpFull.make_current()
322
        
323
        gl.glEnable(gl.GL_DEPTH_TEST)
324
        gl.glClearColor(0.3, 0.3, 0.3, 1.0)
325
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
326
327
        # Change view to perspective projection
328
        gl.glDisable(gl.GL_BLEND)
329
330
        for vp in self.vpManager.viewports:
331
332
            vp.make_current()
333
            self.program.use()
334
            view = vp.camera.getViewMatrix()
335
            self.program.set_uniform_matrix(self.testID2, view)
336
337
            # Draw 3D stuff
338
            gl.glBindVertexArray(self.vao)
339
340
            self.scenegraph.render()
341
342
        gl.glBindVertexArray(0)
343
344
        gl.glEnable(gl.GL_BLEND)
345
        gl.glDisable(gl.GL_DEPTH_TEST)
346
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
347
348
        # Change to orthographic projection to draw the text
349
        self.textProgram.use()
350
        self.vpFull.make_current()
351
        self.text.draw_text(str(self.fpsEstimate) + ' FPS', 0, 10)
352
353
        gl.glDisable(gl.GL_BLEND)
354
        gl.glEnable(gl.GL_DEPTH_TEST)
355
356
357
    def do_run(self):
358
        ''' Process a single loop '''
359
        self.sysEvents.process()
360
        self.update()
361
        self.render()
362
        self.window.flip()
363
        self.fpsTimer.tick()
364
365
        if self.fpsTimer.fpsTime >= 2000:
366
            self.fpsEstimate = self.fpsTimer.get_fps()
367
            print("{:.2f} fps".format(self.fpsEstimate))
368
369
    def run(self):
370
        ''' Called from launcher doesnt exit until the game is quit '''
371
        self.running = True
372
        while self.running:
373
            self.do_run()
374