lazarus/platform/window.go

202 lines
4.1 KiB
Go
Raw Normal View History

package platform
import (
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"
)
type Window struct {
2018-12-31 00:34:53 +00:00
sdlWindow *sdl.Window
sdlGlContext sdl.GLContext
2019-01-01 01:30:59 +00:00
imguiContext *imgui.Context
2018-12-31 00:34:53 +00:00
scene Scene
}
2019-01-01 00:52:53 +00:00
func newWindow(title string, size math.Vec2i, scene Scene) (*Window, error) {
2019-01-01 01:10:45 +00:00
log.Println("window create")
sdlWindow, err := sdl.CreateWindow(
title,
sdl.WINDOWPOS_CENTERED,
sdl.WINDOWPOS_CENTERED,
2019-01-01 00:52:53 +00:00
int32(size.X),
int32(size.Y),
sdl.WINDOW_OPENGL,
)
if err != nil {
return nil, err
}
2018-12-31 00:34:53 +00:00
sdlGlContext, err := sdlWindow.GLCreateContext()
if err != nil {
sdlWindow.Destroy()
return nil, err
}
2018-12-31 21:10:58 +00:00
w := &Window{
sdlWindow: sdlWindow,
sdlGlContext: sdlGlContext,
}
2019-01-01 00:52:53 +00:00
w.makeCurrent()
2019-01-05 20:20:12 +00:00
log.Println("opengl init")
if err := gl.Init(); err != nil {
return nil, err
}
2019-01-01 01:30:59 +00:00
w.imguiContext, err = imgui.New(w.DisplaySize(), w.BufferSize())
2018-12-31 21:10:58 +00:00
if err != nil {
w.Destroy()
return nil, err
}
2018-12-31 00:34:53 +00:00
2019-01-01 00:52:53 +00:00
if err := w.SetScene(scene); err != nil {
2018-12-31 00:34:53 +00:00
w.Destroy()
return nil, err
}
2018-12-31 00:34:53 +00:00
return w, nil
}
2019-01-01 00:52:53 +00:00
func (w *Window) SetScene(scene Scene) error {
if w.scene == scene {
return nil
}
2019-01-01 01:10:45 +00:00
log.Printf("scene transition \"%v\" => \"%v\"\n", sceneName(w.scene), sceneName(scene))
2019-01-01 00:52:53 +00:00
if sceneDestroyer, ok := w.scene.(SceneDestroyer); ok {
2019-01-01 01:10:45 +00:00
log.Printf("scene notify destroy \"%s\"\n", sceneName(w.scene))
2019-01-01 00:52:53 +00:00
if err := sceneDestroyer.Destroy(w); err != nil {
return err
}
}
w.scene = scene
if sceneCreator, ok := scene.(SceneCreator); ok {
2019-01-01 01:10:45 +00:00
log.Printf("scene notify create \"%s\"\n", sceneName(w.scene))
2019-01-01 00:52:53 +00:00
if err := sceneCreator.Create(w); err != nil {
return err
}
}
return nil
}
func (w *Window) Destroy() error {
2018-12-31 21:10:58 +00:00
if w == nil || w.sdlWindow == nil {
return nil
}
2019-01-01 00:52:53 +00:00
w.makeCurrent()
if err := w.SetScene(nil); err != nil {
return err
}
if err := w.imguiContext.Destroy(); err != nil {
return err
}
2019-01-01 00:52:53 +00:00
w.imguiContext = nil
2018-12-31 00:34:53 +00:00
sdl.GLDeleteContext(w.sdlGlContext)
w.sdlGlContext = nil
if err := w.sdlWindow.Destroy(); err != nil {
return err
}
w.sdlWindow = nil
2019-01-01 01:10:45 +00:00
log.Println("window destroy")
2018-12-31 21:40:02 +00:00
removeWindow(w)
2019-01-01 01:10:45 +00:00
return nil
}
func (w *Window) CreateTextureRgba(colors []math.Color4b, size math.Vec2i) (graphics.Texture, error) {
2019-01-01 01:30:59 +00:00
w.makeCurrent()
2018-12-31 17:59:58 +00:00
return newTextureFromRgba(colors, size)
}
func (w *Window) CreateTextureRgb(colors []math.Color3b, size math.Vec2i) (graphics.Texture, error) {
2019-01-01 01:30:59 +00:00
w.makeCurrent()
2018-12-31 18:54:33 +00:00
return newTextureFromRgb(colors, size)
}
func (w *Window) RenderTexture(texture graphics.Texture, position math.Vec2i) {
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()
}
2018-12-31 21:10:58 +00:00
func (w *Window) DisplaySize() math.Vec2i {
width, height := w.sdlWindow.GetSize()
return math.Vec2i{X: int(width), Y: int(height)}
}
func (w *Window) BufferSize() math.Vec2i {
width, height := w.sdlWindow.GLGetDrawableSize()
return math.Vec2i{X: int(width), Y: int(height)}
}
2019-01-01 01:30:59 +00:00
func (w *Window) Imgui() *imgui.Context {
return w.imguiContext
}
2019-01-01 00:52:53 +00:00
func (w *Window) advance() (bool, error) {
w.makeCurrent()
2018-12-31 00:34:53 +00:00
2018-12-31 21:10:58 +00:00
displaySize := w.DisplaySize()
w.imguiContext.SetDisplaySize(displaySize)
bufferSize := w.BufferSize()
w.imguiContext.SetBufferSize(bufferSize)
w.imguiContext.BeginFrame()
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
2019-01-01 00:52:53 +00:00
if sceneAdvancer, ok := w.scene.(SceneAdvancer); ok {
if err := sceneAdvancer.Advance(w); err != nil {
return false, err
}
}
2018-12-31 21:10:58 +00:00
w.imguiContext.EndFrame()
w.sdlWindow.GLSwap()
2019-01-01 00:52:53 +00:00
return w.scene != nil, nil
}
2018-12-31 21:10:58 +00:00
func (w *Window) processEvent(event sdl.Event) (bool, error) {
return w.imguiContext.ProcessEvent(event)
}
2019-01-01 00:52:53 +00:00
func (w *Window) makeCurrent() {
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
}