| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- // 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.
- // +build !wasm
- package app
- import (
- "fmt"
- "github.com/g3n/engine/audio/al"
- "github.com/g3n/engine/audio/vorbis"
- "github.com/g3n/engine/renderer"
- "github.com/g3n/engine/window"
- "time"
- )
- // Desktop application defaults
- const (
- title = "G3N Application"
- width = 800
- height = 600
- )
- // 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() *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()
- // Initialize frame time
- app.frameStart = time.Now()
- // Set up recurring calls to user's update function
- for true {
- // 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.Now().Sub(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
- fmt.Println("LOGGING")
- log.Info("%s version: %s", al.GetString(al.Vendor), al.GetString(al.Version))
- log.Info("%s", vorbis.VersionString())
- return nil
- }
|