-
Notifications
You must be signed in to change notification settings - Fork 293
/
app-desktop.go
150 lines (129 loc) · 4.25 KB
/
app-desktop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2016 The G3N Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !wasm
// +build !wasm
package app
import (
"fmt"
"time"
"github.com/g3n/engine/audio/al"
"github.com/g3n/engine/audio/vorbis"
"github.com/g3n/engine/renderer"
"github.com/g3n/engine/window"
)
// Application
type Application struct {
window.IWindow // Embedded GlfwWindow
keyState *window.KeyState // Keep track of keyboard state
renderer *renderer.Renderer // Renderer object
audioDev *al.Device // Default audio device
startTime time.Time // Application start time
frameStart time.Time // Frame start time
frameDelta time.Duration // Duration of last frame
}
// App returns the Application singleton, creating it the first time.
func App(width, height int, title string) *Application {
// Return singleton if already created
if a != nil {
return a
}
a = new(Application)
// Initialize window
err := window.Init(width, height, title)
if err != nil {
panic(err)
}
a.IWindow = window.Get()
a.openDefaultAudioDevice() // Set up audio
a.keyState = window.NewKeyState(a) // Create KeyState
// Create renderer and add default shaders
a.renderer = renderer.NewRenderer(a.Gls())
err = a.renderer.AddDefaultShaders()
if err != nil {
panic(fmt.Errorf("AddDefaultShaders:%v", err))
}
return a
}
// Run starts the update loop.
// It calls the user-provided update function every frame.
func (a *Application) Run(update func(rend *renderer.Renderer, deltaTime time.Duration)) {
// Initialize start and frame time
a.startTime = time.Now()
a.frameStart = time.Now()
// Set up recurring calls to user's update function
for {
// If Exit() was called or there was an attempt to close the window dispatch OnExit event for subscribers.
// If no subscriber cancelled the event, terminate the application.
if a.IWindow.(*window.GlfwWindow).ShouldClose() {
a.Dispatch(OnExit, nil)
// TODO allow for cancelling exit e.g. showing dialog asking the user if he/she wants to save changes
// if exit was cancelled {
// a.IWindow.(*window.GlfwWindow).SetShouldClose(false)
// } else {
break
// }
}
// Update frame start and frame delta
now := time.Now()
a.frameDelta = now.Sub(a.frameStart)
a.frameStart = now
// Call user's update function
update(a.renderer, a.frameDelta)
// Swap buffers and poll events
a.IWindow.(*window.GlfwWindow).SwapBuffers()
a.IWindow.(*window.GlfwWindow).PollEvents()
}
// Close default audio device
if a.audioDev != nil {
al.CloseDevice(a.audioDev)
}
// Destroy window
a.Destroy()
}
// Exit requests to terminate the application
// Application will dispatch OnQuit events to registered subscribers which
// can cancel the process by calling CancelDispatch().
func (a *Application) Exit() {
a.IWindow.(*window.GlfwWindow).SetShouldClose(true)
}
// Renderer returns the application's renderer.
func (a *Application) Renderer() *renderer.Renderer {
return a.renderer
}
// KeyState returns the application's KeyState.
func (a *Application) KeyState() *window.KeyState {
return a.keyState
}
// RunTime returns the elapsed duration since the call to Run().
func (a *Application) RunTime() time.Duration {
return time.Since(a.startTime)
}
// openDefaultAudioDevice opens the default audio device setting it to the current context
func (a *Application) openDefaultAudioDevice() error {
// Opens default audio device
var err error
a.audioDev, err = al.OpenDevice("")
if err != nil {
return fmt.Errorf("opening OpenAL default device: %s", err)
}
// Check for OpenAL effects extension support
var attribs []int
if al.IsExtensionPresent("ALC_EXT_EFX") {
attribs = []int{al.MAX_AUXILIARY_SENDS, 4}
}
// Create audio context
acx, err := al.CreateContext(a.audioDev, attribs)
if err != nil {
return fmt.Errorf("creating OpenAL context: %s", err)
}
// Makes the context the current one
err = al.MakeContextCurrent(acx)
if err != nil {
return fmt.Errorf("setting OpenAL context current: %s", err)
}
// Logs audio library versions
log.Info("%s version: %s", al.GetString(al.Vendor), al.GetString(al.Version))
log.Info("%s", vorbis.VersionString())
return nil
}