state control through scenes
This commit is contained in:
parent
60e8f19535
commit
557608155d
@ -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
|
||||
}
|
||||
|
||||
func CreateWindow(title string, width, height int, scene Scene) (*Window, error) {
|
||||
if !singleton.isInit {
|
||||
return nil, ErrWasNotInit
|
||||
singleton.sdlIsInit = true
|
||||
}
|
||||
|
||||
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
15
platform/scene.go
Normal 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
|
||||
}
|
@ -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)
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user