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")
|
ErrWasNotInit = errors.New("imgui backend was not initialized")
|
||||||
)
|
)
|
||||||
|
|
||||||
var state struct {
|
var singleton struct {
|
||||||
isInit bool
|
isInit bool
|
||||||
buttonsDown [3]bool
|
buttonsDown [3]bool
|
||||||
lastTime uint64
|
lastTime uint64
|
||||||
@ -24,11 +24,11 @@ var state struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Init() error {
|
func Init() error {
|
||||||
if state.isInit {
|
if singleton.isInit {
|
||||||
return ErrAlreadyInit
|
return ErrAlreadyInit
|
||||||
}
|
}
|
||||||
|
|
||||||
state.context = imgui.CreateContext(nil)
|
singleton.context = imgui.CreateContext(nil)
|
||||||
|
|
||||||
keys := map[int]int{
|
keys := map[int]int{
|
||||||
imgui.KeyTab: sdl.SCANCODE_TAB,
|
imgui.KeyTab: sdl.SCANCODE_TAB,
|
||||||
@ -60,30 +60,30 @@ func Init() error {
|
|||||||
io.KeyMap(imguiKey, nativeKey)
|
io.KeyMap(imguiKey, nativeKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.fontTexture = createFontTexture()
|
singleton.fontTexture = createFontTexture()
|
||||||
state.isInit = true
|
singleton.isInit = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown() error {
|
func Shutdown() error {
|
||||||
if !state.isInit {
|
if !singleton.isInit {
|
||||||
return ErrWasNotInit
|
return ErrWasNotInit
|
||||||
}
|
}
|
||||||
|
|
||||||
state.isInit = false
|
singleton.isInit = false
|
||||||
|
|
||||||
destroyFontTexture(state.fontTexture)
|
destroyFontTexture(singleton.fontTexture)
|
||||||
state.fontTexture = 0
|
singleton.fontTexture = 0
|
||||||
|
|
||||||
state.context.Destroy()
|
singleton.context.Destroy()
|
||||||
state.context = nil
|
singleton.context = nil
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFrame(windowSize math.Vec2i) error {
|
func NewFrame(windowSize math.Vec2i) error {
|
||||||
if !state.isInit {
|
if !singleton.isInit {
|
||||||
return ErrWasNotInit
|
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)
|
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||||
frequency := sdl.GetPerformanceFrequency()
|
frequency := sdl.GetPerformanceFrequency()
|
||||||
currentTime := sdl.GetPerformanceCounter()
|
currentTime := sdl.GetPerformanceCounter()
|
||||||
if state.lastTime > 0 {
|
if singleton.lastTime > 0 {
|
||||||
io.SetDeltaTime(float32(currentTime-state.lastTime) / float32(frequency))
|
io.SetDeltaTime(float32(currentTime-singleton.lastTime) / float32(frequency))
|
||||||
} else {
|
} else {
|
||||||
io.SetDeltaTime(1.0 / 60.0)
|
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.
|
// 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()
|
x, y, state := sdl.GetMouseState()
|
||||||
for i, button := range []uint32{sdl.BUTTON_LEFT, sdl.BUTTON_RIGHT, sdl.BUTTON_MIDDLE} {
|
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)
|
io.SetMouseButtonDown(i, singleton.buttonsDown[i] || (state&sdl.Button(button)) != 0)
|
||||||
state.buttonsDown[i] = false
|
singleton.buttonsDown[i] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
io.SetMousePosition(imgui.Vec2{X: float32(x), Y: float32(y)})
|
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.
|
// 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.
|
// 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) {
|
func ProcessEvent(event sdl.Event) (bool, error) {
|
||||||
if !state.isInit {
|
if !singleton.isInit {
|
||||||
return false, ErrWasNotInit
|
return false, ErrWasNotInit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,13 +143,13 @@ func ProcessEvent(event sdl.Event) (bool, error) {
|
|||||||
buttonEvent := event.(*sdl.MouseButtonEvent)
|
buttonEvent := event.(*sdl.MouseButtonEvent)
|
||||||
switch buttonEvent.Button {
|
switch buttonEvent.Button {
|
||||||
case sdl.BUTTON_LEFT:
|
case sdl.BUTTON_LEFT:
|
||||||
state.buttonsDown[0] = true
|
singleton.buttonsDown[0] = true
|
||||||
break
|
break
|
||||||
case sdl.BUTTON_RIGHT:
|
case sdl.BUTTON_RIGHT:
|
||||||
state.buttonsDown[1] = true
|
singleton.buttonsDown[1] = true
|
||||||
break
|
break
|
||||||
case sdl.BUTTON_MIDDLE:
|
case sdl.BUTTON_MIDDLE:
|
||||||
state.buttonsDown[2] = true
|
singleton.buttonsDown[2] = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -178,9 +178,9 @@ func ProcessEvent(event sdl.Event) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL2 Render function.
|
// 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 {
|
func Render(windowSize, fbSize math.Vec2i, drawData imgui.DrawData) error {
|
||||||
if !state.isInit {
|
if !singleton.isInit {
|
||||||
return ErrWasNotInit
|
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!
|
// 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
|
var lastTexture int32
|
||||||
gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture)
|
gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture)
|
||||||
var lastPolygonMode [2]int32
|
var lastPolygonMode [2]int32
|
||||||
@ -296,7 +296,7 @@ func createFontTexture() uint32 {
|
|||||||
// Store our identifier
|
// Store our identifier
|
||||||
io.Fonts().SetTextureID(imgui.TextureID(fontTexture))
|
io.Fonts().SetTextureID(imgui.TextureID(fontTexture))
|
||||||
|
|
||||||
// Restore state
|
// Restore singleton
|
||||||
gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture))
|
gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture))
|
||||||
return fontTexture
|
return fontTexture
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,11 @@ var (
|
|||||||
|
|
||||||
var state struct {
|
var state struct {
|
||||||
isInit bool
|
isInit bool
|
||||||
windows []Window
|
windows []*window
|
||||||
|
}
|
||||||
|
|
||||||
|
type Scene interface {
|
||||||
|
Advance()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init() error {
|
func Init() error {
|
||||||
@ -69,12 +73,13 @@ func ProcessEvents() error {
|
|||||||
return ErrWasNotInit
|
return ErrWasNotInit
|
||||||
}
|
}
|
||||||
|
|
||||||
var terminate bool
|
for running := true; running; {
|
||||||
for !terminate {
|
advanceWindows()
|
||||||
|
renderWindows()
|
||||||
|
|
||||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||||
switch event.(type) {
|
if !handleEvent(event) {
|
||||||
case *sdl.QuitEvent:
|
running = false
|
||||||
terminate = true
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,12 +90,12 @@ func ProcessEvents() error {
|
|||||||
return nil
|
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 {
|
if !state.isInit {
|
||||||
return nil, ErrWasNotInit
|
return nil, ErrWasNotInit
|
||||||
}
|
}
|
||||||
|
|
||||||
window, err := newWindow(title, width, height)
|
window, err := newWindow(title, width, height, scene)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -99,3 +104,24 @@ func CreateWindow(title string, width, height int) (Window, error) {
|
|||||||
|
|
||||||
return window, err
|
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
|
package platform
|
||||||
|
|
||||||
import "github.com/veandco/go-sdl2/sdl"
|
import (
|
||||||
|
"github.com/FooSoft/lazarus/math"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
type Window interface {
|
type Window interface {
|
||||||
Destroy() error
|
Destroy() error
|
||||||
@ -10,9 +13,10 @@ type window struct {
|
|||||||
sdlWindow *sdl.Window
|
sdlWindow *sdl.Window
|
||||||
sdlGlContext sdl.GLContext
|
sdlGlContext sdl.GLContext
|
||||||
sdlRenderer *sdl.Renderer
|
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(
|
sdlWindow, err := sdl.CreateWindow(
|
||||||
title,
|
title,
|
||||||
sdl.WINDOWPOS_CENTERED,
|
sdl.WINDOWPOS_CENTERED,
|
||||||
@ -37,7 +41,7 @@ func newWindow(title string, width, height int) (Window, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &window{sdlWindow, sdlGlContext, sdlRenderer}, nil
|
return &window{sdlWindow, sdlGlContext, sdlRenderer, scene}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) Destroy() error {
|
func (w *window) Destroy() error {
|
||||||
@ -52,3 +56,21 @@ func (w *window) Destroy() error {
|
|||||||
|
|
||||||
return nil
|
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