| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // 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
- )
- // OnExit is the event generated by Application when the user
- // tries to close the window or the Exit() method is called.
- const OnExit = "app.OnExit"
- // 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
- frameStart time.Time // Frame start time
- frameDelta time.Duration // Duration of last frame
- }
- // Application singleton
- var app *Application
- // App returns the Application singleton, creating it the first time.
- func App() *Application {
- // Return singleton if already created
- if app != nil {
- return app
- }
- app = new(Application)
- // Initialize window
- err := window.Init(width, height, title)
- if err != nil {
- panic(err)
- }
- app.IWindow = window.Get()
- app.openDefaultAudioDevice() // Set up audio
- app.keyState = window.NewKeyState(app) // Create KeyState
- // Create renderer and add default shaders
- app.renderer = renderer.NewRenderer(app.Gls())
- err = app.renderer.AddDefaultShaders()
- if err != nil {
- panic(fmt.Errorf("AddDefaultShaders:%v", err))
- }
- return app
- }
- // Run starts the update loop.
- // It calls the user-provided update function every frame.
- func (app *Application) Run(update func(renderer *renderer.Renderer, deltaTime time.Duration)) {
- // 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, terminates the application.
- if app.IWindow.(*window.GlfwWindow).ShouldClose() {
- canceled := app.Dispatch(OnExit, nil) // TODO implement the same in app-browser
- if canceled {
- app.IWindow.(*window.GlfwWindow).SetShouldClose(false)
- } else {
- break
- }
- }
- // Update frame start and frame delta
- now := time.Now()
- app.frameDelta = now.Sub(app.frameStart)
- app.frameStart = now
- // Call user's update function
- update(app.renderer, app.frameDelta)
- // Swap buffers and poll events
- app.IWindow.(*window.GlfwWindow).SwapBuffers()
- app.IWindow.(*window.GlfwWindow).PollEvents()
- }
- // Close default audio device
- if app.audioDev != nil {
- al.CloseDevice(app.audioDev)
- }
- // Destroy window
- app.Destroy()
- }
- // Exit requests to terminate the application
- // Application will dispatch OnQuit events to registered subscribers which
- // can cancel the process by calling CancelDispatch().
- func (app *Application) Exit() {
- app.IWindow.(*window.GlfwWindow).SetShouldClose(true)
- }
- // Renderer returns the application's renderer.
- func (app *Application) Renderer() *renderer.Renderer {
- return app.renderer
- }
- // KeyState returns the application's KeyState.
- func (app *Application) KeyState() *window.KeyState {
- return app.keyState
- }
- // openDefaultAudioDevice opens the default audio device setting it to the current context
- func (app *Application) openDefaultAudioDevice() error {
- // Opens default audio device
- var err error
- app.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(app.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
- }
|