lazarus/platform/window.go

232 lines
4.8 KiB
Go
Raw Normal View History

package platform
import (
"errors"
2019-01-01 01:10:45 +00:00
"log"
"github.com/FooSoft/lazarus/graphics"
"github.com/FooSoft/lazarus/math"
2018-12-31 21:14:13 +00:00
"github.com/FooSoft/lazarus/platform/imgui"
2018-12-31 00:34:53 +00:00
"github.com/go-gl/gl/v2.1/gl"
"github.com/veandco/go-sdl2/sdl"
)
var (
ErrWindowExists = errors.New("only one window can exist at a time")
ErrWindowNotExists = errors.New("no window has been created")
)
type Scene interface {
Name() string
}
type SceneCreator interface {
Create() error
}
type SceneAdvancer interface {
Advance() error
}
type SceneDestroyer interface {
Destroy() error
}
var windowState struct {
2018-12-31 00:34:53 +00:00
sdlWindow *sdl.Window
sdlGlContext sdl.GLContext
scene Scene
}
func WindowCreate(title string, size math.Vec2i, scene Scene) error {
if WindowIsCreated() {
return ErrWindowExists
}
var err error
log.Println("window create")
if windowState.sdlWindow, err = sdl.CreateWindow(title, sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, int32(size.X), int32(size.Y), sdl.WINDOW_OPENGL); err != nil {
return err
}
log.Println("window gl context create")
if windowState.sdlGlContext, err = windowState.sdlWindow.GLCreateContext(); err != nil {
WindowDestroy()
return err
2018-12-31 21:10:58 +00:00
}
log.Println("window gl context make current")
windowState.sdlWindow.GLMakeCurrent(windowState.sdlGlContext)
2019-01-01 00:52:53 +00:00
log.Println("window gl init")
2019-01-05 20:20:12 +00:00
if err := gl.Init(); err != nil {
WindowDestroy()
return err
2019-01-05 20:20:12 +00:00
}
if err := imgui.Create(); err != nil {
WindowDestroy()
return err
2018-12-31 21:10:58 +00:00
}
2018-12-31 00:34:53 +00:00
if err := WindowSetScene(scene); err != nil {
WindowDestroy()
return err
}
return nil
}
func WindowSetScene(scene Scene) error {
if !WindowIsCreated() {
return ErrWindowNotExists
}
if windowState.scene == scene {
2019-01-01 00:52:53 +00:00
return nil
}
sceneName := func(s Scene) string {
if s == nil {
return "<nil>"
} else {
return s.Name()
}
}
2019-01-01 01:10:45 +00:00
if sceneDestroyer, ok := windowState.scene.(SceneDestroyer); ok {
log.Printf("window scene notify destroy \"%s\"\n", sceneName(windowState.scene))
if err := sceneDestroyer.Destroy(); err != nil {
2019-01-01 00:52:53 +00:00
return err
}
}
log.Printf("window scene transition \"%v\" => \"%v\"\n", sceneName(windowState.scene), sceneName(scene))
windowState.scene = scene
2019-01-01 00:52:53 +00:00
if sceneCreator, ok := scene.(SceneCreator); ok {
log.Printf("window scene notify create \"%s\"\n", sceneName(windowState.scene))
if err := sceneCreator.Create(); err != nil {
2019-01-01 00:52:53 +00:00
return err
}
}
return nil
}
func WindowDestroy() error {
if !WindowIsCreated() {
return nil
}
if err := WindowSetScene(nil); err != nil {
2019-01-01 00:52:53 +00:00
return err
}
if err := imgui.Destroy(); err != nil {
return err
}
2018-12-31 00:34:53 +00:00
log.Println("window gl context destroy")
sdl.GLDeleteContext(windowState.sdlGlContext)
windowState.sdlGlContext = nil
log.Println("window destroy")
if err := windowState.sdlWindow.Destroy(); err != nil {
return err
}
windowState.sdlWindow = nil
2019-01-01 01:10:45 +00:00
return nil
}
func WindowRenderTexture(texture graphics.Texture, position math.Vec2i) error {
if !WindowIsCreated() {
return ErrWindowNotExists
}
2018-12-31 18:54:33 +00:00
2018-12-31 00:34:53 +00:00
size := texture.Size()
gl.Enable(gl.TEXTURE_2D)
gl.BindTexture(gl.TEXTURE_2D, uint32(texture.Id()))
2018-12-31 00:34:53 +00:00
gl.Begin(gl.QUADS)
gl.TexCoord2f(0, 0)
gl.Vertex2f(0, 0)
gl.TexCoord2f(0, 1)
gl.Vertex2f(0, float32(size.Y))
gl.TexCoord2f(1, 1)
gl.Vertex2f(float32(size.X), float32(size.Y))
gl.TexCoord2f(1, 0)
gl.Vertex2f(float32(size.X), 0)
gl.End()
return nil
}
func WindowDisplaySize() (math.Vec2i, error) {
if !WindowIsCreated() {
return math.Vec2i{}, ErrWindowNotExists
}
width, height := windowState.sdlWindow.GetSize()
return math.Vec2i{X: int(width), Y: int(height)}, nil
2018-12-31 21:10:58 +00:00
}
func WindowIsCreated() bool {
return windowState.sdlWindow != nil
2018-12-31 21:10:58 +00:00
}
func windowBufferSize() (math.Vec2i, error) {
if !WindowIsCreated() {
return math.Vec2i{}, ErrWindowNotExists
}
width, height := windowState.sdlWindow.GLGetDrawableSize()
return math.Vec2i{X: int(width), Y: int(height)}, nil
2019-01-01 01:30:59 +00:00
}
func windowAdvance() (bool, error) {
if !WindowIsCreated() {
return false, ErrWindowNotExists
}
displaySize, err := WindowDisplaySize()
if err != nil {
return false, err
}
2018-12-31 00:34:53 +00:00
bufferSize, err := windowBufferSize()
if err != nil {
return false, err
}
2018-12-31 21:10:58 +00:00
imgui.BeginFrame(displaySize, bufferSize)
2018-12-31 19:46:12 +00:00
gl.Viewport(0, 0, int32(displaySize.X), int32(displaySize.Y))
2018-12-31 00:34:53 +00:00
gl.Clear(gl.COLOR_BUFFER_BIT)
gl.MatrixMode(gl.PROJECTION)
gl.LoadIdentity()
2018-12-31 19:46:12 +00:00
gl.Ortho(0, float64(displaySize.X), float64(displaySize.Y), 0, -1, 1)
2018-12-31 00:34:53 +00:00
gl.MatrixMode(gl.MODELVIEW)
gl.LoadIdentity()
2018-12-30 01:04:37 +00:00
if sceneAdvancer, ok := windowState.scene.(SceneAdvancer); ok {
if err := sceneAdvancer.Advance(); err != nil {
2019-01-01 00:52:53 +00:00
return false, err
}
}
imgui.EndFrame()
windowState.sdlWindow.GLSwap()
2019-01-01 00:52:53 +00:00
return windowState.scene != nil, nil
}
func windowProcessEvent(event sdl.Event) (bool, error) {
if !WindowIsCreated() {
return false, ErrWindowNotExists
}
2019-01-01 00:52:53 +00:00
return imgui.ProcessEvent(event)
2019-01-01 00:52:53 +00:00
}