|
@@ -1,568 +0,0 @@
|
|
|
-package application
|
|
|
|
|
-
|
|
|
|
|
-import (
|
|
|
|
|
- "flag"
|
|
|
|
|
- "fmt"
|
|
|
|
|
- "os"
|
|
|
|
|
- "runtime"
|
|
|
|
|
- "runtime/pprof"
|
|
|
|
|
- "runtime/trace"
|
|
|
|
|
- "time"
|
|
|
|
|
-
|
|
|
|
|
- "github.com/g3n/engine/audio/al"
|
|
|
|
|
- "github.com/g3n/engine/audio/vorbis"
|
|
|
|
|
- "github.com/g3n/engine/camera"
|
|
|
|
|
- "github.com/g3n/engine/camera/control"
|
|
|
|
|
- "github.com/g3n/engine/core"
|
|
|
|
|
- "github.com/g3n/engine/gls"
|
|
|
|
|
- "github.com/g3n/engine/gui"
|
|
|
|
|
- "github.com/g3n/engine/math32"
|
|
|
|
|
- "github.com/g3n/engine/renderer"
|
|
|
|
|
- "github.com/g3n/engine/util/logger"
|
|
|
|
|
- "github.com/g3n/engine/window"
|
|
|
|
|
-)
|
|
|
|
|
-
|
|
|
|
|
-// Application is a standard application object which can be used as a base for G3N applications.
|
|
|
|
|
-// It creates a Window, OpenGL state, default cameras, default scene and Gui and has a method to run the render loop.
|
|
|
|
|
-type Application struct {
|
|
|
|
|
- core.Dispatcher // Embedded event dispatcher
|
|
|
|
|
- core.TimerManager // Embedded timer manager
|
|
|
|
|
- wmgr window.IWindowManager // Window manager
|
|
|
|
|
- win window.IWindow // Application window
|
|
|
|
|
- gl *gls.GLS // OpenGL state
|
|
|
|
|
- log *logger.Logger // Default application logger
|
|
|
|
|
- renderer *renderer.Renderer // Renderer object
|
|
|
|
|
- camPersp *camera.Perspective // Perspective camera
|
|
|
|
|
- camOrtho *camera.Orthographic // Orthographic camera
|
|
|
|
|
- camera camera.ICamera // Current camera
|
|
|
|
|
- orbit *control.OrbitControl // Camera orbit controller
|
|
|
|
|
- frameRater *FrameRater // Render loop frame rater
|
|
|
|
|
- keyState *KeyState // State of keys
|
|
|
|
|
- audioDev *al.Device // Default audio device
|
|
|
|
|
- scene *core.Node // Node container for 3D tests
|
|
|
|
|
- guiroot *gui.Root // Gui root panel
|
|
|
|
|
- frameCount uint64 // Frame counter
|
|
|
|
|
- frameTime time.Time // Time at the start of the frame
|
|
|
|
|
- frameDelta time.Duration // Time delta from previous frame
|
|
|
|
|
- startTime time.Time // Time at the start of the render loop
|
|
|
|
|
- fullScreen *bool // Full screen option
|
|
|
|
|
- swapInterval *int // Swap interval option
|
|
|
|
|
- targetFPS *uint // Target FPS option
|
|
|
|
|
- noglErrors *bool // No OpenGL check errors options
|
|
|
|
|
- cpuProfile *string // File to write cpu profile to
|
|
|
|
|
- execTrace *string // File to write execution trace data to
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Options defines initial options passed to the application creation function
|
|
|
|
|
-type Options struct {
|
|
|
|
|
- Title string // Initial window title
|
|
|
|
|
- Height int // Initial window height (default is screen width)
|
|
|
|
|
- Width int // Initial window width (default is screen height)
|
|
|
|
|
- Fullscreen bool // Window full screen flag (default = false)
|
|
|
|
|
- LogPrefix string // Log prefix (default = "")
|
|
|
|
|
- LogLevel int // Initial log level (default = DEBUG)
|
|
|
|
|
- EnableFlags bool // Enable command line flags (default = false)
|
|
|
|
|
- TargetFPS uint // Desired frames per second rate (default = 60)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// OnBeforeRender is the event generated by Application just before rendering the scene/gui
|
|
|
|
|
-const OnBeforeRender = "util.application.OnBeforeRender"
|
|
|
|
|
-
|
|
|
|
|
-// OnAfterRender is the event generated by Application just after rendering the scene/gui
|
|
|
|
|
-const OnAfterRender = "util.application.OnAfterRender"
|
|
|
|
|
-
|
|
|
|
|
-// OnQuit is the event generated by Application when the user tries to close the window
|
|
|
|
|
-// or the Quit() method is called.
|
|
|
|
|
-const OnQuit = "util.application.OnQuit"
|
|
|
|
|
-
|
|
|
|
|
-// appInstance contains the pointer to the single Application instance
|
|
|
|
|
-var appInstance *Application
|
|
|
|
|
-
|
|
|
|
|
-// Create creates and returns the application object using the specified options.
|
|
|
|
|
-// This function must be called only once.
|
|
|
|
|
-func Create(ops Options) (*Application, error) {
|
|
|
|
|
-
|
|
|
|
|
- if appInstance != nil {
|
|
|
|
|
- return nil, fmt.Errorf("Application already created")
|
|
|
|
|
- }
|
|
|
|
|
- app := new(Application)
|
|
|
|
|
- appInstance = app
|
|
|
|
|
- app.Dispatcher.Initialize()
|
|
|
|
|
- app.TimerManager.Initialize()
|
|
|
|
|
-
|
|
|
|
|
- // Initialize options defaults
|
|
|
|
|
- app.fullScreen = new(bool)
|
|
|
|
|
- app.swapInterval = new(int)
|
|
|
|
|
- app.targetFPS = new(uint)
|
|
|
|
|
- app.noglErrors = new(bool)
|
|
|
|
|
- app.cpuProfile = new(string)
|
|
|
|
|
- app.execTrace = new(string)
|
|
|
|
|
- *app.swapInterval = -1
|
|
|
|
|
- *app.targetFPS = 60
|
|
|
|
|
-
|
|
|
|
|
- // Options parameter overrides some options
|
|
|
|
|
- if ops.TargetFPS != 0 {
|
|
|
|
|
- *app.fullScreen = ops.Fullscreen
|
|
|
|
|
- *app.targetFPS = ops.TargetFPS
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Creates flags if requested (override options defaults)
|
|
|
|
|
- if ops.EnableFlags {
|
|
|
|
|
- app.fullScreen = flag.Bool("fullscreen", *app.fullScreen, "Starts application with full screen")
|
|
|
|
|
- app.swapInterval = flag.Int("swapinterval", *app.swapInterval, "Sets the swap buffers interval to this value")
|
|
|
|
|
- app.targetFPS = flag.Uint("targetfps", *app.targetFPS, "Sets the frame rate in frames per second")
|
|
|
|
|
- app.noglErrors = flag.Bool("noglerrors", *app.noglErrors, "Do not check OpenGL errors at each call (may increase FPS)")
|
|
|
|
|
- app.cpuProfile = flag.String("cpuprofile", *app.cpuProfile, "Activate cpu profiling writing profile to the specified file")
|
|
|
|
|
- app.execTrace = flag.String("exectrace", *app.execTrace, "Activate execution tracer writing data to the specified file")
|
|
|
|
|
- flag.Parse()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Creates application logger
|
|
|
|
|
- app.log = logger.New(ops.LogPrefix, nil)
|
|
|
|
|
- app.log.AddWriter(logger.NewConsole(false))
|
|
|
|
|
- app.log.SetFormat(logger.FTIME | logger.FMICROS)
|
|
|
|
|
- app.log.SetLevel(ops.LogLevel)
|
|
|
|
|
-
|
|
|
|
|
- // Window event handling must run on the main OS thread
|
|
|
|
|
- runtime.LockOSThread()
|
|
|
|
|
-
|
|
|
|
|
- // Get the window manager
|
|
|
|
|
- wmgr, err := window.Manager()
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return nil, err
|
|
|
|
|
- }
|
|
|
|
|
- app.wmgr = wmgr
|
|
|
|
|
-
|
|
|
|
|
- // Get the screen resolution
|
|
|
|
|
- swidth, sheight := app.wmgr.ScreenResolution(nil)
|
|
|
|
|
- var posx, posy int
|
|
|
|
|
- // If not full screen, sets the window size
|
|
|
|
|
- if !*app.fullScreen {
|
|
|
|
|
- if ops.Width != 0 {
|
|
|
|
|
- posx = (swidth - ops.Width) / 2
|
|
|
|
|
- if posx < 0 {
|
|
|
|
|
- posx = 0
|
|
|
|
|
- }
|
|
|
|
|
- swidth = ops.Width
|
|
|
|
|
- }
|
|
|
|
|
- if ops.Height != 0 {
|
|
|
|
|
- posy = (sheight - ops.Height) / 2
|
|
|
|
|
- if posy < 0 {
|
|
|
|
|
- posy = 0
|
|
|
|
|
- }
|
|
|
|
|
- sheight = ops.Height
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Creates window
|
|
|
|
|
- win, err := app.wmgr.CreateWindow(swidth, sheight, ops.Title, *app.fullScreen)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return nil, err
|
|
|
|
|
- }
|
|
|
|
|
- win.SetPos(posx, posy)
|
|
|
|
|
- app.win = win
|
|
|
|
|
- app.gl = win.Gls()
|
|
|
|
|
-
|
|
|
|
|
- // Checks OpenGL errors
|
|
|
|
|
- app.gl.SetCheckErrors(!*app.noglErrors)
|
|
|
|
|
-
|
|
|
|
|
- // Logs OpenGL version
|
|
|
|
|
- glVersion := app.Gl().GetString(gls.VERSION)
|
|
|
|
|
- app.log.Info("OpenGL version: %s", glVersion)
|
|
|
|
|
-
|
|
|
|
|
- // Clears the screen
|
|
|
|
|
- cc := math32.NewColor("gray")
|
|
|
|
|
- app.gl.ClearColor(cc.R, cc.G, cc.B, 1)
|
|
|
|
|
- app.gl.Clear(gls.DEPTH_BUFFER_BIT | gls.STENCIL_BUFFER_BIT | gls.COLOR_BUFFER_BIT)
|
|
|
|
|
-
|
|
|
|
|
- // Creates KeyState
|
|
|
|
|
- app.keyState = NewKeyState(win)
|
|
|
|
|
-
|
|
|
|
|
- // Creates perspective camera
|
|
|
|
|
- width, height := app.win.Size()
|
|
|
|
|
- aspect := float32(width) / float32(height)
|
|
|
|
|
- app.camPersp = camera.NewPerspective(65, aspect, 0.01, 1000)
|
|
|
|
|
-
|
|
|
|
|
- // Creates orthographic camera
|
|
|
|
|
- app.camOrtho = camera.NewOrthographic(-2, 2, 2, -2, 0.01, 100)
|
|
|
|
|
- app.camOrtho.SetPosition(0, 0, 3)
|
|
|
|
|
- app.camOrtho.LookAt(&math32.Vector3{0, 0, 0})
|
|
|
|
|
- app.camOrtho.SetZoom(1.0)
|
|
|
|
|
-
|
|
|
|
|
- // Default camera is perspective
|
|
|
|
|
- app.camera = app.camPersp
|
|
|
|
|
-
|
|
|
|
|
- // Creates orbit camera control
|
|
|
|
|
- // It is important to do this after the root panel subscription
|
|
|
|
|
- // to avoid GUI events being propagated to the orbit control.
|
|
|
|
|
- app.orbit = control.NewOrbitControl(app.camera, app.win)
|
|
|
|
|
-
|
|
|
|
|
- // Creates scene for 3D objects
|
|
|
|
|
- app.scene = core.NewNode()
|
|
|
|
|
-
|
|
|
|
|
- // Creates gui root panel
|
|
|
|
|
- app.guiroot = gui.NewRoot(app.gl, app.win)
|
|
|
|
|
- app.guiroot.SetColor(math32.NewColor("silver"))
|
|
|
|
|
-
|
|
|
|
|
- // Creates renderer
|
|
|
|
|
- app.renderer = renderer.NewRenderer(app.gl)
|
|
|
|
|
- err = app.renderer.AddDefaultShaders()
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return nil, fmt.Errorf("Error from AddDefaulShaders:%v", err)
|
|
|
|
|
- }
|
|
|
|
|
- app.renderer.SetScene(app.scene)
|
|
|
|
|
- app.renderer.SetGui(app.guiroot)
|
|
|
|
|
-
|
|
|
|
|
- // Create frame rater
|
|
|
|
|
- app.frameRater = NewFrameRater(*app.targetFPS)
|
|
|
|
|
-
|
|
|
|
|
- // Sets the default window resize event handler
|
|
|
|
|
- app.win.SubscribeID(window.OnWindowSize, app, func(evname string, ev interface{}) {
|
|
|
|
|
- app.OnWindowResize()
|
|
|
|
|
- })
|
|
|
|
|
- app.OnWindowResize()
|
|
|
|
|
-
|
|
|
|
|
- return app, nil
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Get returns the application single instance or nil
|
|
|
|
|
-// if the application was not created yet
|
|
|
|
|
-func Get() *Application {
|
|
|
|
|
-
|
|
|
|
|
- return appInstance
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Log returns the application logger
|
|
|
|
|
-func (app *Application) Log() *logger.Logger {
|
|
|
|
|
-
|
|
|
|
|
- return app.log
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Window returns the application window
|
|
|
|
|
-func (app *Application) Window() window.IWindow {
|
|
|
|
|
-
|
|
|
|
|
- return app.win
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// KeyState returns the application KeyState
|
|
|
|
|
-func (app *Application) KeyState() *KeyState {
|
|
|
|
|
-
|
|
|
|
|
- return app.keyState
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Gl returns the OpenGL state
|
|
|
|
|
-func (app *Application) Gl() *gls.GLS {
|
|
|
|
|
-
|
|
|
|
|
- return app.gl
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Gui returns the current application Gui root panel
|
|
|
|
|
-func (app *Application) Gui() *gui.Root {
|
|
|
|
|
-
|
|
|
|
|
- return app.guiroot
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Scene returns the current application 3D scene
|
|
|
|
|
-func (app *Application) Scene() *core.Node {
|
|
|
|
|
-
|
|
|
|
|
- return app.scene
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetScene sets the 3D scene to be rendered
|
|
|
|
|
-func (app *Application) SetScene(scene *core.Node) {
|
|
|
|
|
-
|
|
|
|
|
- app.renderer.SetScene(scene)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetGui sets the root panel of the gui to be rendered
|
|
|
|
|
-func (app *Application) SetGui(root *gui.Root) {
|
|
|
|
|
-
|
|
|
|
|
- app.guiroot = root
|
|
|
|
|
- app.renderer.SetGui(app.guiroot)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetPanel3D sets the gui panel inside which the 3D scene is shown.
|
|
|
|
|
-func (app *Application) SetPanel3D(panel3D gui.IPanel) {
|
|
|
|
|
-
|
|
|
|
|
- app.renderer.SetGuiPanel3D(panel3D)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Panel3D returns the current gui panel where the 3D scene is shown.
|
|
|
|
|
-func (app *Application) Panel3D() gui.IPanel {
|
|
|
|
|
-
|
|
|
|
|
- return app.renderer.Panel3D()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// CameraPersp returns the application perspective camera
|
|
|
|
|
-func (app *Application) CameraPersp() *camera.Perspective {
|
|
|
|
|
-
|
|
|
|
|
- return app.camPersp
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// CameraOrtho returns the application orthographic camera
|
|
|
|
|
-func (app *Application) CameraOrtho() *camera.Orthographic {
|
|
|
|
|
-
|
|
|
|
|
- return app.camOrtho
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Camera returns the current application camera
|
|
|
|
|
-func (app *Application) Camera() camera.ICamera {
|
|
|
|
|
-
|
|
|
|
|
- return app.camera
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetCamera sets the current application camera
|
|
|
|
|
-func (app *Application) SetCamera(cam camera.ICamera) {
|
|
|
|
|
-
|
|
|
|
|
- app.camera = cam
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Orbit returns the current camera orbit control
|
|
|
|
|
-func (app *Application) Orbit() *control.OrbitControl {
|
|
|
|
|
-
|
|
|
|
|
- return app.orbit
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetOrbit sets the camera orbit control
|
|
|
|
|
-func (app *Application) SetOrbit(oc *control.OrbitControl) {
|
|
|
|
|
-
|
|
|
|
|
- app.orbit = oc
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// FrameRater returns the FrameRater object
|
|
|
|
|
-func (app *Application) FrameRater() *FrameRater {
|
|
|
|
|
-
|
|
|
|
|
- return app.frameRater
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// FrameCount returns the total number of frames since the call to Run()
|
|
|
|
|
-func (app *Application) FrameCount() uint64 {
|
|
|
|
|
-
|
|
|
|
|
- return app.frameCount
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// FrameDelta returns the duration of the previous frame
|
|
|
|
|
-func (app *Application) FrameDelta() time.Duration {
|
|
|
|
|
-
|
|
|
|
|
- return app.frameDelta
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// FrameDeltaSeconds returns the duration of the previous frame
|
|
|
|
|
-// in float32 seconds
|
|
|
|
|
-func (app *Application) FrameDeltaSeconds() float32 {
|
|
|
|
|
-
|
|
|
|
|
- return float32(app.frameDelta.Seconds())
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// RunTime returns the duration since the call to Run()
|
|
|
|
|
-func (app *Application) RunTime() time.Duration {
|
|
|
|
|
-
|
|
|
|
|
- return time.Now().Sub(app.startTime)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// RunSeconds returns the elapsed time in seconds since the call to Run()
|
|
|
|
|
-func (app *Application) RunSeconds() float32 {
|
|
|
|
|
-
|
|
|
|
|
- return float32(time.Now().Sub(app.startTime).Seconds())
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Renderer returns the application renderer
|
|
|
|
|
-func (app *Application) Renderer() *renderer.Renderer {
|
|
|
|
|
-
|
|
|
|
|
- return app.renderer
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetCPUProfile must be called before Run() and sets the file name for cpu profiling.
|
|
|
|
|
-// If set the cpu profiling starts before running the render loop and continues
|
|
|
|
|
-// till the end of the application.
|
|
|
|
|
-func (app *Application) SetCPUProfile(fname string) {
|
|
|
|
|
-
|
|
|
|
|
- *app.cpuProfile = fname
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// SetOnWindowResize replaces the default window resize handler with the specified one
|
|
|
|
|
-func (app *Application) SetOnWindowResize(f func(evname string, ev interface{})) {
|
|
|
|
|
-
|
|
|
|
|
- app.win.UnsubscribeID(window.OnWindowSize, app)
|
|
|
|
|
- app.win.SubscribeID(window.OnWindowSize, app, f)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Run runs the application render loop
|
|
|
|
|
-func (app *Application) Run() error {
|
|
|
|
|
-
|
|
|
|
|
- // Set swap interval
|
|
|
|
|
- if *app.swapInterval >= 0 {
|
|
|
|
|
- app.wmgr.SetSwapInterval(*app.swapInterval)
|
|
|
|
|
- app.log.Debug("Swap interval set to: %v", *app.swapInterval)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Start profiling if requested
|
|
|
|
|
- if *app.cpuProfile != "" {
|
|
|
|
|
- f, err := os.Create(*app.cpuProfile)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- defer f.Close()
|
|
|
|
|
- err = pprof.StartCPUProfile(f)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- defer pprof.StopCPUProfile()
|
|
|
|
|
- app.log.Info("Started writing CPU profile to: %s", *app.cpuProfile)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Start execution trace if requested
|
|
|
|
|
- if *app.execTrace != "" {
|
|
|
|
|
- f, err := os.Create(*app.execTrace)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- defer f.Close()
|
|
|
|
|
- err = trace.Start(f)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- defer trace.Stop()
|
|
|
|
|
- app.log.Info("Started writing execution trace to: %s", *app.execTrace)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- app.startTime = time.Now()
|
|
|
|
|
- app.frameTime = time.Now()
|
|
|
|
|
-
|
|
|
|
|
- // Render loop
|
|
|
|
|
- for true {
|
|
|
|
|
- // If was requested to terminate the application by trying to close the window
|
|
|
|
|
- // or by calling Quit(), dispatch OnQuit event for subscribers.
|
|
|
|
|
- // If no subscriber cancelled the event, terminates the application.
|
|
|
|
|
- if app.win.ShouldClose() {
|
|
|
|
|
- canceled := app.Dispatch(OnQuit, nil)
|
|
|
|
|
- if canceled {
|
|
|
|
|
- app.win.SetShouldClose(false)
|
|
|
|
|
- } else {
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Starts measuring this frame
|
|
|
|
|
- app.frameRater.Start()
|
|
|
|
|
-
|
|
|
|
|
- // Updates frame start and time delta in context
|
|
|
|
|
- now := time.Now()
|
|
|
|
|
- app.frameDelta = now.Sub(app.frameTime)
|
|
|
|
|
- app.frameTime = now
|
|
|
|
|
-
|
|
|
|
|
- // Process root panel timers
|
|
|
|
|
- if app.Gui() != nil {
|
|
|
|
|
- app.Gui().TimerManager.ProcessTimers()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Process application timers
|
|
|
|
|
- app.ProcessTimers()
|
|
|
|
|
-
|
|
|
|
|
- // Dispatch before render event
|
|
|
|
|
- app.Dispatch(OnBeforeRender, nil)
|
|
|
|
|
-
|
|
|
|
|
- // Renders the current scene and/or gui
|
|
|
|
|
- rendered, err := app.renderer.Render(app.camera)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Poll input events and process them
|
|
|
|
|
- app.wmgr.PollEvents()
|
|
|
|
|
-
|
|
|
|
|
- if rendered {
|
|
|
|
|
- app.win.SwapBuffers()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Dispatch after render event
|
|
|
|
|
- app.Dispatch(OnAfterRender, nil)
|
|
|
|
|
-
|
|
|
|
|
- // Controls the frame rate
|
|
|
|
|
- app.frameRater.Wait()
|
|
|
|
|
- app.frameCount++
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Dispose resources
|
|
|
|
|
- if app.scene != nil {
|
|
|
|
|
- app.scene.DisposeChildren(true)
|
|
|
|
|
- }
|
|
|
|
|
- if app.guiroot != nil {
|
|
|
|
|
- app.guiroot.DisposeChildren(true)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Close default audio device
|
|
|
|
|
- if app.audioDev != nil {
|
|
|
|
|
- al.CloseDevice(app.audioDev)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Terminates window manager
|
|
|
|
|
- app.wmgr.Terminate()
|
|
|
|
|
-
|
|
|
|
|
- // This is important when using the execution tracer
|
|
|
|
|
- runtime.UnlockOSThread()
|
|
|
|
|
- return nil
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 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("Error: %s opening OpenAL default device", err)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Checks for OpenAL effects extension support
|
|
|
|
|
- audioEFX := false
|
|
|
|
|
- if al.IsExtensionPresent("ALC_EXT_EFX") {
|
|
|
|
|
- audioEFX = true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Creates audio context with auxiliary sends
|
|
|
|
|
- var attribs []int
|
|
|
|
|
- if audioEFX {
|
|
|
|
|
- attribs = []int{al.MAX_AUXILIARY_SENDS, 4}
|
|
|
|
|
- }
|
|
|
|
|
- acx, err := al.CreateContext(app.audioDev, attribs)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return fmt.Errorf("Error creating OpenAL context:%s", err)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Makes the context the current one
|
|
|
|
|
- err = al.MakeContextCurrent(acx)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return fmt.Errorf("Error setting OpenAL context current:%s", err)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Logs audio library versions
|
|
|
|
|
- app.log.Info("%s version: %s", al.GetString(al.Vendor), al.GetString(al.Version))
|
|
|
|
|
- app.log.Info("%s", vorbis.VersionString())
|
|
|
|
|
- return nil
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// Quit requests to terminate the application
|
|
|
|
|
-// Application will dispatch OnQuit events to registered subscriber which
|
|
|
|
|
-// can cancel the process by calling CancelDispatch().
|
|
|
|
|
-func (app *Application) Quit() {
|
|
|
|
|
-
|
|
|
|
|
- app.win.SetShouldClose(true)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// OnWindowResize is default handler for window resize events.
|
|
|
|
|
-func (app *Application) OnWindowResize() {
|
|
|
|
|
-
|
|
|
|
|
- // Get framebuffer size and sets the viewport accordingly
|
|
|
|
|
- width, height := app.win.FramebufferSize()
|
|
|
|
|
- app.gl.Viewport(0, 0, int32(width), int32(height))
|
|
|
|
|
-
|
|
|
|
|
- // Sets perspective camera aspect ratio
|
|
|
|
|
- aspect := float32(width) / float32(height)
|
|
|
|
|
- app.Camera().SetAspect(aspect)
|
|
|
|
|
-
|
|
|
|
|
- // Sets the GUI root panel size to the size of the framebuffer
|
|
|
|
|
- if app.guiroot != nil {
|
|
|
|
|
- app.guiroot.SetSize(float32(width), float32(height))
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|