work on getting platform to abstract updating and rendering
add "Scene" interface to provide customization point for clients
This commit is contained in:
parent
5d95d2ef77
commit
7c024b537e
@ -15,7 +15,7 @@ var (
|
||||
ErrWasNotInit = errors.New("imgui backend was not initialized")
|
||||
)
|
||||
|
||||
var state struct {
|
||||
var singleton struct {
|
||||
isInit bool
|
||||
buttonsDown [3]bool
|
||||
lastTime uint64
|
||||
@ -24,11 +24,11 @@ var state struct {
|
||||
}
|
||||
|
||||
func Init() error {
|
||||
if state.isInit {
|
||||
if singleton.isInit {
|
||||
return ErrAlreadyInit
|
||||
}
|
||||
|
||||
state.context = imgui.CreateContext(nil)
|
||||
singleton.context = imgui.CreateContext(nil)
|
||||
|
||||
keys := map[int]int{
|
||||
imgui.KeyTab: sdl.SCANCODE_TAB,
|
||||
@ -60,30 +60,30 @@ func Init() error {
|
||||
io.KeyMap(imguiKey, nativeKey)
|
||||
}
|
||||
|
||||
state.fontTexture = createFontTexture()
|
||||
state.isInit = true
|
||||
singleton.fontTexture = createFontTexture()
|
||||
singleton.isInit = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Shutdown() error {
|
||||
if !state.isInit {
|
||||
if !singleton.isInit {
|
||||
return ErrWasNotInit
|
||||
}
|
||||
|
||||
state.isInit = false
|
||||
singleton.isInit = false
|
||||
|
||||
destroyFontTexture(state.fontTexture)
|
||||
state.fontTexture = 0
|
||||
destroyFontTexture(singleton.fontTexture)
|
||||
singleton.fontTexture = 0
|
||||
|
||||
state.context.Destroy()
|
||||
state.context = nil
|
||||
singleton.context.Destroy()
|
||||
singleton.context = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewFrame(windowSize math.Vec2i) error {
|
||||
if !state.isInit {
|
||||
if !singleton.isInit {
|
||||
return ErrWasNotInit
|
||||
}
|
||||
|
||||
@ -94,18 +94,18 @@ func NewFrame(windowSize math.Vec2i) error {
|
||||
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||
frequency := sdl.GetPerformanceFrequency()
|
||||
currentTime := sdl.GetPerformanceCounter()
|
||||
if state.lastTime > 0 {
|
||||
io.SetDeltaTime(float32(currentTime-state.lastTime) / float32(frequency))
|
||||
if singleton.lastTime > 0 {
|
||||
io.SetDeltaTime(float32(currentTime-singleton.lastTime) / float32(frequency))
|
||||
} else {
|
||||
io.SetDeltaTime(1.0 / 60.0)
|
||||
}
|
||||
state.lastTime = currentTime
|
||||
singleton.lastTime = currentTime
|
||||
|
||||
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
x, y, state := sdl.GetMouseState()
|
||||
for i, button := range []uint32{sdl.BUTTON_LEFT, sdl.BUTTON_RIGHT, sdl.BUTTON_MIDDLE} {
|
||||
io.SetMouseButtonDown(i, state.buttonsDown[i] || (state&sdl.Button(button)) != 0)
|
||||
state.buttonsDown[i] = false
|
||||
io.SetMouseButtonDown(i, singleton.buttonsDown[i] || (state&sdl.Button(button)) != 0)
|
||||
singleton.buttonsDown[i] = false
|
||||
}
|
||||
|
||||
io.SetMousePosition(imgui.Vec2{X: float32(x), Y: float32(y)})
|
||||
@ -120,7 +120,7 @@ func NewFrame(windowSize math.Vec2i) error {
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||
func ProcessEvent(event sdl.Event) (bool, error) {
|
||||
if !state.isInit {
|
||||
if !singleton.isInit {
|
||||
return false, ErrWasNotInit
|
||||
}
|
||||
|
||||
@ -143,13 +143,13 @@ func ProcessEvent(event sdl.Event) (bool, error) {
|
||||
buttonEvent := event.(*sdl.MouseButtonEvent)
|
||||
switch buttonEvent.Button {
|
||||
case sdl.BUTTON_LEFT:
|
||||
state.buttonsDown[0] = true
|
||||
singleton.buttonsDown[0] = true
|
||||
break
|
||||
case sdl.BUTTON_RIGHT:
|
||||
state.buttonsDown[1] = true
|
||||
singleton.buttonsDown[1] = true
|
||||
break
|
||||
case sdl.BUTTON_MIDDLE:
|
||||
state.buttonsDown[2] = true
|
||||
singleton.buttonsDown[2] = true
|
||||
break
|
||||
}
|
||||
return true, nil
|
||||
@ -178,9 +178,9 @@ func ProcessEvent(event sdl.Event) (bool, error) {
|
||||
}
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL singleton explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||
func Render(windowSize, fbSize math.Vec2i, drawData imgui.DrawData) error {
|
||||
if !state.isInit {
|
||||
if !singleton.isInit {
|
||||
return ErrWasNotInit
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ func Render(windowSize, fbSize math.Vec2i, drawData imgui.DrawData) error {
|
||||
})
|
||||
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
// Setup render singleton: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
var lastTexture int32
|
||||
gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture)
|
||||
var lastPolygonMode [2]int32
|
||||
@ -296,7 +296,7 @@ func createFontTexture() uint32 {
|
||||
// Store our identifier
|
||||
io.Fonts().SetTextureID(imgui.TextureID(fontTexture))
|
||||
|
||||
// Restore state
|
||||
// Restore singleton
|
||||
gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture))
|
||||
return fontTexture
|
||||
}
|
||||
|
@ -17,7 +17,11 @@ var (
|
||||
|
||||
var state struct {
|
||||
isInit bool
|
||||
windows []Window
|
||||
windows []*window
|
||||
}
|
||||
|
||||
type Scene interface {
|
||||
Advance()
|
||||
}
|
||||
|
||||
func Init() error {
|
||||
@ -69,12 +73,13 @@ func ProcessEvents() error {
|
||||
return ErrWasNotInit
|
||||
}
|
||||
|
||||
var terminate bool
|
||||
for !terminate {
|
||||
for running := true; running; {
|
||||
advanceWindows()
|
||||
renderWindows()
|
||||
|
||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||
switch event.(type) {
|
||||
case *sdl.QuitEvent:
|
||||
terminate = true
|
||||
if !handleEvent(event) {
|
||||
running = false
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -85,12 +90,12 @@ func ProcessEvents() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateWindow(title string, width, height int) (Window, error) {
|
||||
func CreateWindow(title string, width, height int, scene Scene) (Window, error) {
|
||||
if !state.isInit {
|
||||
return nil, ErrWasNotInit
|
||||
}
|
||||
|
||||
window, err := newWindow(title, width, height)
|
||||
window, err := newWindow(title, width, height, scene)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -99,3 +104,24 @@ func CreateWindow(title string, width, height int) (Window, error) {
|
||||
|
||||
return window, err
|
||||
}
|
||||
|
||||
func advanceWindows() {
|
||||
for _, window := range state.windows {
|
||||
window.advance()
|
||||
}
|
||||
}
|
||||
|
||||
func renderWindows() {
|
||||
for _, window := range state.windows {
|
||||
window.render()
|
||||
}
|
||||
}
|
||||
|
||||
func handleEvent(event sdl.Event) bool {
|
||||
switch event.(type) {
|
||||
case *sdl.QuitEvent:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package platform
|
||||
|
||||
import "github.com/veandco/go-sdl2/sdl"
|
||||
import (
|
||||
"github.com/FooSoft/lazarus/math"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
type Window interface {
|
||||
Destroy() error
|
||||
@ -10,9 +13,10 @@ type window struct {
|
||||
sdlWindow *sdl.Window
|
||||
sdlGlContext sdl.GLContext
|
||||
sdlRenderer *sdl.Renderer
|
||||
scene Scene
|
||||
}
|
||||
|
||||
func newWindow(title string, width, height int) (Window, error) {
|
||||
func newWindow(title string, width, height int, scene Scene) (*window, error) {
|
||||
sdlWindow, err := sdl.CreateWindow(
|
||||
title,
|
||||
sdl.WINDOWPOS_CENTERED,
|
||||
@ -37,7 +41,7 @@ func newWindow(title string, width, height int) (Window, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &window{sdlWindow, sdlGlContext, sdlRenderer}, nil
|
||||
return &window{sdlWindow, sdlGlContext, sdlRenderer, scene}, nil
|
||||
}
|
||||
|
||||
func (w *window) Destroy() error {
|
||||
@ -52,3 +56,21 @@ func (w *window) Destroy() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *window) advance() {
|
||||
w.scene.Advance()
|
||||
}
|
||||
|
||||
func (w *window) render() {
|
||||
w.sdlWindow.GLMakeCurrent(w.sdlGlContext)
|
||||
}
|
||||
|
||||
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)}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user