forked from EngoEngine/engo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscene.go
More file actions
124 lines (100 loc) · 3.16 KB
/
Copy pathscene.go
File metadata and controls
124 lines (100 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package engo
import (
"fmt"
"engo.io/ecs"
)
var scenes = make(map[string]*sceneWrapper)
// Scene represents a screen ingame.
// i.e.: main menu, settings, but also the game itself
type Scene interface {
// Preload is called before loading resources
Preload()
// Setup is called before the main loop
Setup(*ecs.World)
// Type returns a unique string representation of the Scene, used to identify it
Type() string
}
// Shower is an optional interface a Scene can implement, indicating it'll have custom behavior
// whenever the Scene gets shown again after being hidden (due to switching to other Scenes)
type Shower interface {
// Show is called whenever the other Scene becomes inactive, and this one becomes the active one
Show()
}
// Hider is an optional interface a Scene can implement, indicating it'll have custom behavior
// whenever the Scene get hidden to make room fr other Scenes.
type Hider interface {
// Hide is called when an other Scene becomes active
Hide()
}
// Exiter is an optional interface a Scene can implement, indicating it'll have custom behavior
// whenever the game get closed.
type Exiter interface {
// Exit is called when the user or the system requests to close the game
// This should be used to cleanup or prompt user if they're sure they want to close
// To prevent the default action (close/exit) make sure to set OverrideCloseAction in
// your RunOpts to `true`. You should then handle the exiting of the program by calling
// engo.Exit()
Exit()
}
type sceneWrapper struct {
scene Scene
world *ecs.World
mailbox *MessageManager
}
// CurrentScene returns the SceneWorld that is currently active
func CurrentScene() Scene {
return currentScene
}
// SetScene sets the currentScene to the given Scene, and
// optionally forcing to create a new ecs.World that goes with it.
func SetScene(s Scene, forceNewWorld bool) {
// Break down currentScene
if currentScene != nil {
if hider, ok := currentScene.(Hider); ok {
hider.Hide()
}
}
// Register Scene if needed
wrapper, registered := scenes[s.Type()]
if !registered {
RegisterScene(s)
wrapper = scenes[s.Type()]
}
// Initialize new Scene / World if needed
var doSetup bool
if wrapper.world == nil || forceNewWorld {
wrapper.world = &ecs.World{}
wrapper.mailbox = &MessageManager{}
doSetup = true
}
// Do the switch
currentScene = s
currentWorld = wrapper.world
Mailbox = wrapper.mailbox
// doSetup is true whenever we're (re)initializing the Scene
if doSetup {
s.Preload()
wrapper.mailbox.listeners = make(map[string][]MessageHandler)
s.Setup(wrapper.world)
} else {
if shower, ok := currentScene.(Shower); ok {
shower.Show()
}
}
}
// RegisterScene registers the `Scene`, so it can later be used by `SetSceneByName`
func RegisterScene(s Scene) {
_, ok := scenes[s.Type()]
if !ok {
scenes[s.Type()] = &sceneWrapper{scene: s}
}
}
// SetSceneByName does a lookup for the `Scene` where its `Type()` equals `name`, and then sets it as current `Scene`
func SetSceneByName(name string, forceNewWorld bool) error {
scene, ok := scenes[name]
if !ok {
return fmt.Errorf("scene not registered: %s", name)
}
SetScene(scene.scene, forceNewWorld)
return nil
}