state control through scenes
This commit is contained in:
parent
60e8f19535
commit
557608155d
@ -1,57 +1,25 @@
|
|||||||
package platform
|
package platform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/FooSoft/lazarus/math"
|
||||||
"github.com/go-gl/gl/v2.1/gl"
|
"github.com/go-gl/gl/v2.1/gl"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrAlreadyInit = errors.New("platform is already initialized")
|
|
||||||
ErrWasNotInit = errors.New("platform was not initialized")
|
|
||||||
)
|
|
||||||
|
|
||||||
var singleton struct {
|
var singleton struct {
|
||||||
isInit bool
|
sdlIsInit bool
|
||||||
windows []*Window
|
windows []*Window
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handle uintptr
|
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) {
|
func Advance() (bool, error) {
|
||||||
if !singleton.isInit {
|
if err := advanceWindows(); err != nil {
|
||||||
return false, ErrWasNotInit
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
advanceWindows()
|
|
||||||
|
|
||||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||||
switch event.(type) {
|
switch event.(type) {
|
||||||
case *sdl.QuitEvent:
|
case *sdl.QuitEvent:
|
||||||
@ -63,32 +31,25 @@ func Advance() (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return len(singleton.windows) > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown() error {
|
func NewWindow(title string, size math.Vec2i, scene Scene) (*Window, error) {
|
||||||
if !singleton.isInit {
|
if !singleton.sdlIsInit {
|
||||||
return ErrWasNotInit
|
runtime.LockOSThread()
|
||||||
|
|
||||||
|
if err := sdl.Init(sdl.INIT_VIDEO); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, w := range singleton.windows {
|
if err := gl.Init(); err != nil {
|
||||||
if err := w.Destroy(); err != nil {
|
return nil, err
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
singleton.windows = nil
|
singleton.sdlIsInit = true
|
||||||
singleton.isInit = false
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateWindow(title string, width, height int, scene Scene) (*Window, error) {
|
w, err := newWindow(title, size, scene)
|
||||||
if !singleton.isInit {
|
|
||||||
return nil, ErrWasNotInit
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := newWindow(title, width, height, scene)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -112,10 +73,23 @@ func removeWindow(window *Window) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func advanceWindows() {
|
func advanceWindows() error {
|
||||||
|
var windowsToRemove []*Window
|
||||||
for _, window := range singleton.windows {
|
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 {
|
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
|
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_MAJOR_VERSION, 2)
|
||||||
sdl.GLSetAttribute(sdl.GL_CONTEXT_MINOR_VERSION, 1)
|
sdl.GLSetAttribute(sdl.GL_CONTEXT_MINOR_VERSION, 1)
|
||||||
sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1)
|
sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1)
|
||||||
@ -23,8 +23,8 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
|
|||||||
title,
|
title,
|
||||||
sdl.WINDOWPOS_CENTERED,
|
sdl.WINDOWPOS_CENTERED,
|
||||||
sdl.WINDOWPOS_CENTERED,
|
sdl.WINDOWPOS_CENTERED,
|
||||||
int32(width),
|
int32(size.X),
|
||||||
int32(height),
|
int32(size.Y),
|
||||||
sdl.WINDOW_OPENGL,
|
sdl.WINDOW_OPENGL,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,16 +40,17 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
|
|||||||
w := &Window{
|
w := &Window{
|
||||||
sdlWindow: sdlWindow,
|
sdlWindow: sdlWindow,
|
||||||
sdlGlContext: sdlGlContext,
|
sdlGlContext: sdlGlContext,
|
||||||
scene: scene,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.makeCurrent()
|
||||||
|
|
||||||
w.imguiContext, err = imgui_backend.New(w.DisplaySize(), w.BufferSize())
|
w.imguiContext, err = imgui_backend.New(w.DisplaySize(), w.BufferSize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Destroy()
|
w.Destroy()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scene.Init(w); err != nil {
|
if err := w.SetScene(scene); err != nil {
|
||||||
w.Destroy()
|
w.Destroy()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -57,15 +58,43 @@ func newWindow(title string, width, height int, scene Scene) (*Window, error) {
|
|||||||
return w, nil
|
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 {
|
func (w *Window) Destroy() error {
|
||||||
if w == nil || w.sdlWindow == nil {
|
if w == nil || w.sdlWindow == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := w.scene.Shutdown(w); err != nil {
|
w.makeCurrent()
|
||||||
|
|
||||||
|
if err := w.SetScene(nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.scene = nil
|
|
||||||
|
if err := w.imguiContext.Destroy(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.imguiContext = nil
|
||||||
|
|
||||||
sdl.GLDeleteContext(w.sdlGlContext)
|
sdl.GLDeleteContext(w.sdlGlContext)
|
||||||
w.sdlGlContext = nil
|
w.sdlGlContext = nil
|
||||||
@ -115,8 +144,8 @@ func (w *Window) BufferSize() math.Vec2i {
|
|||||||
return math.Vec2i{X: int(width), Y: int(height)}
|
return math.Vec2i{X: int(width), Y: int(height)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) advance() {
|
func (w *Window) advance() (bool, error) {
|
||||||
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
|
w.makeCurrent()
|
||||||
|
|
||||||
displaySize := w.DisplaySize()
|
displaySize := w.DisplaySize()
|
||||||
w.imguiContext.SetDisplaySize(displaySize)
|
w.imguiContext.SetDisplaySize(displaySize)
|
||||||
@ -133,12 +162,23 @@ func (w *Window) advance() {
|
|||||||
gl.MatrixMode(gl.MODELVIEW)
|
gl.MatrixMode(gl.MODELVIEW)
|
||||||
gl.LoadIdentity()
|
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.imguiContext.EndFrame()
|
||||||
w.sdlWindow.GLSwap()
|
w.sdlWindow.GLSwap()
|
||||||
|
|
||||||
|
return w.scene != nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) processEvent(event sdl.Event) (bool, error) {
|
func (w *Window) processEvent(event sdl.Event) (bool, error) {
|
||||||
return w.imguiContext.ProcessEvent(event)
|
return w.imguiContext.ProcessEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Window) makeCurrent() {
|
||||||
|
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -41,15 +41,7 @@ type scene struct {
|
|||||||
frameIndex int32
|
frameIndex int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scene) Init(window *platform.Window) error {
|
func (s *scene) Destroy(window *platform.Window) error {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *scene) Shutdown(window *platform.Window) error {
|
|
||||||
if s.texture == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.texture.Destroy()
|
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("Size: %+v", frame.Size))
|
||||||
imgui.Text(fmt.Sprintf("Offset: %+v", frame.Offset))
|
imgui.Text(fmt.Sprintf("Offset: %+v", frame.Offset))
|
||||||
|
|
||||||
|
if imgui.Button("Exit") {
|
||||||
|
window.SetScene(nil)
|
||||||
|
}
|
||||||
|
|
||||||
if directionIndex != s.directionIndex || frameIndex != s.frameIndex {
|
if directionIndex != s.directionIndex || frameIndex != s.frameIndex {
|
||||||
s.directionIndex = directionIndex
|
s.directionIndex = directionIndex
|
||||||
s.frameIndex = frameIndex
|
s.frameIndex = frameIndex
|
||||||
@ -146,11 +142,8 @@ func main() {
|
|||||||
palette = dat.NewFromGrayscale()
|
palette = dat.NewFromGrayscale()
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.Init()
|
|
||||||
defer platform.Shutdown()
|
|
||||||
|
|
||||||
scene := &scene{sprite: sprite, palette: palette}
|
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 {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user