state control through scenes

This commit is contained in:
Alex Yatskov 2018-12-31 16:52:53 -08:00
parent 60e8f19535
commit 557608155d
4 changed files with 104 additions and 82 deletions

View File

@ -1,57 +1,25 @@
package platform
import (
"errors"
"runtime"
"github.com/FooSoft/lazarus/math"
"github.com/go-gl/gl/v2.1/gl"
"github.com/veandco/go-sdl2/sdl"
)
var (
ErrAlreadyInit = errors.New("platform is already initialized")
ErrWasNotInit = errors.New("platform was not initialized")
)
var singleton struct {
isInit bool
sdlIsInit bool
windows []*Window
}
type Handle uintptr
type Scene interface {
Init(window *Window) error
Advance(window *Window) error
Shutdown(window *Window) error
}
func Init() error {
if singleton.isInit {
return ErrAlreadyInit
}
runtime.LockOSThread()
if err := sdl.Init(sdl.INIT_VIDEO); err != nil {
return err
}
if err := gl.Init(); err != nil {
return err
}
singleton.isInit = true
return nil
}
func Advance() (bool, error) {
if !singleton.isInit {
return false, ErrWasNotInit
if err := advanceWindows(); err != nil {
return false, err
}
advanceWindows()
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
@ -63,32 +31,25 @@ func Advance() (bool, error) {
}
}
return true, nil
return len(singleton.windows) > 0, nil
}
func Shutdown() error {
if !singleton.isInit {
return ErrWasNotInit
func NewWindow(title string, size math.Vec2i, scene Scene) (*Window, error) {
if !singleton.sdlIsInit {
runtime.LockOSThread()
if err := sdl.Init(sdl.INIT_VIDEO); err != nil {
return nil, err
}
for _, w := range singleton.windows {
if err := w.Destroy(); err != nil {
return err
}
if err := gl.Init(); err != nil {
return nil, err
}
singleton.windows = nil
singleton.isInit = false
return nil
singleton.sdlIsInit = true
}
func CreateWindow(title string, width, height int, scene Scene) (*Window, error) {
if !singleton.isInit {
return nil, ErrWasNotInit
}
w, err := newWindow(title, width, height, scene)
w, err := newWindow(title, size, scene)
if err != nil {
return nil, err
}
@ -112,10 +73,23 @@ func removeWindow(window *Window) bool {
return false
}
func advanceWindows() {
func advanceWindows() error {
var windowsToRemove []*Window
for _, window := range singleton.windows {
window.advance()
run, err := window.advance()
if err != nil {
return err
}
if !run {
windowsToRemove = append(windowsToRemove, window)
}
}
for _, window := range windowsToRemove {
removeWindow(window)
}
return nil
}
func processWindowEvents(event sdl.Event) error {

15
platform/scene.go Normal file
View File

@ -0,0 +1,15 @@
package platform
type Scene interface{}
type SceneCreator interface {
Create(window *Window) error
}
type SceneAdvancer interface {
Advance(window *Window) error
}
type SceneDestroyer interface {
Destroy(window *Window) error
}

View File

@ -14,7 +14,7 @@ type Window struct {
scene Scene
}
func newWindow(title string, width, height int, scene Scene) (*Window, error) {
func newWindow(title string, size math.Vec2i, scene Scene) (*Window, error) {
sdl.GLSetAttribute(sdl.GL_CONTEXT_MAJOR_VERSION, 2)
sdl.GLSetAttribute(sdl.GL_CONTEXT_MINOR_VERSION, 1)
sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1)
@ -23,8 +23,8 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
title,
sdl.WINDOWPOS_CENTERED,
sdl.WINDOWPOS_CENTERED,
int32(width),
int32(height),
int32(size.X),
int32(size.Y),
sdl.WINDOW_OPENGL,
)
if err != nil {
@ -40,16 +40,17 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
w := &Window{
sdlWindow: sdlWindow,
sdlGlContext: sdlGlContext,
scene: scene,
}
w.makeCurrent()
w.imguiContext, err = imgui_backend.New(w.DisplaySize(), w.BufferSize())
if err != nil {
w.Destroy()
return nil, err
}
if err := scene.Init(w); err != nil {
if err := w.SetScene(scene); err != nil {
w.Destroy()
return nil, err
}
@ -57,15 +58,43 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
return w, nil
}
func (w *Window) SetScene(scene Scene) error {
if w.scene == scene {
return nil
}
if sceneDestroyer, ok := w.scene.(SceneDestroyer); ok {
if err := sceneDestroyer.Destroy(w); err != nil {
return err
}
}
w.scene = scene
if sceneCreator, ok := scene.(SceneCreator); ok {
if err := sceneCreator.Create(w); err != nil {
return err
}
}
return nil
}
func (w *Window) Destroy() error {
if w == nil || w.sdlWindow == nil {
return nil
}
if err := w.scene.Shutdown(w); err != nil {
w.makeCurrent()
if err := w.SetScene(nil); err != nil {
return err
}
w.scene = nil
if err := w.imguiContext.Destroy(); err != nil {
return err
}
w.imguiContext = nil
sdl.GLDeleteContext(w.sdlGlContext)
w.sdlGlContext = nil
@ -115,8 +144,8 @@ func (w *Window) BufferSize() math.Vec2i {
return math.Vec2i{X: int(width), Y: int(height)}
}
func (w *Window) advance() {
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
func (w *Window) advance() (bool, error) {
w.makeCurrent()
displaySize := w.DisplaySize()
w.imguiContext.SetDisplaySize(displaySize)
@ -133,12 +162,23 @@ func (w *Window) advance() {
gl.MatrixMode(gl.MODELVIEW)
gl.LoadIdentity()
w.scene.Advance(w)
if sceneAdvancer, ok := w.scene.(SceneAdvancer); ok {
if err := sceneAdvancer.Advance(w); err != nil {
return false, err
}
}
w.imguiContext.EndFrame()
w.sdlWindow.GLSwap()
return w.scene != nil, nil
}
func (w *Window) processEvent(event sdl.Event) (bool, error) {
return w.imguiContext.ProcessEvent(event)
}
func (w *Window) makeCurrent() {
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
}

View File

@ -41,15 +41,7 @@ type scene struct {
frameIndex int32
}
func (s *scene) Init(window *platform.Window) error {
return nil
}
func (s *scene) Shutdown(window *platform.Window) error {
if s.texture == nil {
return nil
}
func (s *scene) Destroy(window *platform.Window) error {
return s.texture.Destroy()
}
@ -77,6 +69,10 @@ func (s *scene) Advance(window *platform.Window) error {
imgui.Text(fmt.Sprintf("Size: %+v", frame.Size))
imgui.Text(fmt.Sprintf("Offset: %+v", frame.Offset))
if imgui.Button("Exit") {
window.SetScene(nil)
}
if directionIndex != s.directionIndex || frameIndex != s.frameIndex {
s.directionIndex = directionIndex
s.frameIndex = frameIndex
@ -146,11 +142,8 @@ func main() {
palette = dat.NewFromGrayscale()
}
platform.Init()
defer platform.Shutdown()
scene := &scene{sprite: sprite, palette: palette}
window, err := platform.CreateWindow("Viewer", 1280, 720, scene)
window, err := platform.NewWindow("Viewer", math.Vec2i{X: 1024, Y: 768}, scene)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)