mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-18 02:16:23 -05:00
3bdbd5c358
remove unused struct vars that were only stored in order to pass to the next screens consolidate create game code to single method export ScreenMode consts and SetScreenMode method to allow app to create the correct screens Co-authored-by: carrelda <carrelda@git>
143 lines
3.8 KiB
Go
143 lines
3.8 KiB
Go
package d2screen
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
|
)
|
|
|
|
// Screen is an exported interface
|
|
type Screen interface{}
|
|
|
|
// ScreenLoadHandler is an exported interface
|
|
type ScreenLoadHandler interface {
|
|
// OnLoad performs all necessary loading to prepare a screen to be shown such as loading assets, placing and binding
|
|
// of ui elements, etc. This loading is done asynchronously. The provided channel will allow implementations to
|
|
// provide progress via Error, Progress, or Done
|
|
OnLoad(loading LoadingState)
|
|
}
|
|
|
|
// ScreenUnloadHandler is an exported interface
|
|
type ScreenUnloadHandler interface {
|
|
OnUnload() error
|
|
}
|
|
|
|
// ScreenRenderHandler is an exported interface
|
|
type ScreenRenderHandler interface {
|
|
Render(target d2interface.Surface) error
|
|
}
|
|
|
|
// ScreenAdvanceHandler is an exported interface
|
|
type ScreenAdvanceHandler interface {
|
|
Advance(elapsed float64) error
|
|
}
|
|
|
|
var singleton struct {
|
|
nextScreen Screen
|
|
loadingScreen Screen
|
|
loadingState LoadingState
|
|
currentScreen Screen
|
|
}
|
|
|
|
// SetNextScreen is about to set a given screen as next
|
|
func SetNextScreen(screen Screen) {
|
|
singleton.nextScreen = screen
|
|
}
|
|
|
|
// Advance updates the UI on every frame
|
|
func Advance(elapsed float64) error {
|
|
switch {
|
|
case singleton.loadingScreen != nil:
|
|
// this call blocks execution and could lead to deadlock if a screen implements OnLoad incorreclty
|
|
load, ok := <-singleton.loadingState.updates
|
|
if !ok {
|
|
log.Println("loadingState chan should not be closed while in a loading screen")
|
|
}
|
|
if load.err != nil {
|
|
log.Printf("PROBLEM LOADING THE SCREEN: %v", load.err)
|
|
return load.err
|
|
}
|
|
d2gui.ShowLoadScreen(load.progress)
|
|
if load.done {
|
|
singleton.currentScreen = singleton.loadingScreen
|
|
singleton.loadingScreen = nil
|
|
d2gui.ShowCursor()
|
|
d2gui.HideLoadScreen()
|
|
}
|
|
case singleton.nextScreen != nil:
|
|
if handler, ok := singleton.currentScreen.(ScreenUnloadHandler); ok {
|
|
if err := handler.OnUnload(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
d2ui.Reset()
|
|
d2gui.SetLayout(nil)
|
|
|
|
if handler, ok := singleton.nextScreen.(ScreenLoadHandler); ok {
|
|
d2gui.ShowLoadScreen(0)
|
|
d2gui.HideCursor()
|
|
singleton.loadingState = LoadingState{updates: make(chan loadingUpdate)}
|
|
go func() {
|
|
handler.OnLoad(singleton.loadingState)
|
|
singleton.loadingState.Done()
|
|
}()
|
|
singleton.currentScreen = nil
|
|
singleton.loadingScreen = singleton.nextScreen
|
|
} else {
|
|
singleton.currentScreen = singleton.nextScreen
|
|
singleton.loadingScreen = nil
|
|
}
|
|
singleton.nextScreen = nil
|
|
case singleton.currentScreen != nil:
|
|
if handler, ok := singleton.currentScreen.(ScreenAdvanceHandler); ok {
|
|
if err := handler.Advance(elapsed); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Render renders the UI by a given surface
|
|
func Render(surface d2interface.Surface) error {
|
|
if handler, ok := singleton.currentScreen.(ScreenRenderHandler); ok {
|
|
if err := handler.Render(surface); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadingState represents the loading state
|
|
type LoadingState struct {
|
|
updates chan loadingUpdate
|
|
}
|
|
|
|
type loadingUpdate struct {
|
|
progress float64
|
|
err error
|
|
done bool
|
|
}
|
|
|
|
// Error provides a way for callers to report an error during loading.
|
|
func (l *LoadingState) Error(err error) {
|
|
l.updates <- loadingUpdate{err: err}
|
|
}
|
|
|
|
// Progress provides a way for callers to report the ratio between `0` and `1` of the progress made loading a screen.
|
|
func (l *LoadingState) Progress(ratio float64) {
|
|
l.updates <- loadingUpdate{progress: ratio}
|
|
}
|
|
|
|
// Done provides a way for callers to report that screen loading has been completed.
|
|
func (l *LoadingState) Done() {
|
|
l.updates <- loadingUpdate{progress: 1.0}
|
|
l.updates <- loadingUpdate{done: true}
|
|
}
|