-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathsceneLoop.go
131 lines (112 loc) · 3.26 KB
/
sceneLoop.go
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
125
126
127
128
129
130
131
package oak
import (
"context"
"github.com/oakmound/oak/v4/alg/intgeom"
"github.com/oakmound/oak/v4/dlog"
"github.com/oakmound/oak/v4/event"
"github.com/oakmound/oak/v4/oakerr"
"github.com/oakmound/oak/v4/scene"
"github.com/oakmound/oak/v4/timing"
)
// the oak loading scene is a reserved scene
// for preloading assets
const oakLoadingScene = "oak:loading"
func (w *Window) sceneLoop(first string, trackingInputs bool) {
var prevScene string
result := new(scene.Result)
// kick start the draw loop
w.drawCh <- struct{}{}
w.drawCh <- struct{}{}
w.firstScene = first
w.SceneMap.CurrentScene = oakLoadingScene
for {
w.SetViewport(intgeom.Point2{0, 0})
w.RemoveViewportBounds()
dlog.Info(dlog.SceneStarting, w.SceneMap.CurrentScene)
scen, ok := w.SceneMap.GetCurrent()
if !ok {
dlog.Error(dlog.UnknownScene, w.SceneMap.CurrentScene)
if w.ErrorScene != "" {
w.SceneMap.CurrentScene = w.ErrorScene
scen, ok = w.SceneMap.GetCurrent()
if !ok {
go w.exitWithError(oakerr.NotFound{InputName: "ErrorScene"})
return
}
} else {
go w.exitWithError(oakerr.NotFound{InputName: "Scene"})
return
}
}
if trackingInputs {
w.trackInputChanges()
}
gctx, cancel := context.WithCancel(w.ParentContext)
go func() {
scen.Start(&scene.Context{
Context: gctx,
PreviousScene: prevScene,
SceneInput: result.NextSceneInput,
DrawStack: w.DrawStack,
Handler: w.eventHandler,
CallerMap: w.CallerMap,
MouseTree: w.MouseTree,
CollisionTree: w.CollisionTree,
Window: w,
State: &w.State,
})
w.transitionCh <- struct{}{}
}()
w.sceneTransition(result)
// Post transition, begin loading animation
w.drawCh <- struct{}{}
<-w.transitionCh
// Send a signal to resume (or begin) drawing
w.drawCh <- struct{}{}
dlog.Info(dlog.SceneLooping)
enterCancel := event.EnterLoop(w.eventHandler, timing.FPSToFrameDelay(w.FrameRate))
nextSceneOverride := ""
select {
case <-w.ParentContext.Done():
w.Quit()
cancel()
return
case <-w.quitCh:
cancel()
return
case nextSceneOverride = <-w.skipSceneCh:
}
cancel()
dlog.Info(dlog.SceneEnding, w.SceneMap.CurrentScene)
// We don't want enterFrames going off between scenes
enterCancel()
prevScene = w.SceneMap.CurrentScene
// Send a signal to stop drawing
w.drawCh <- struct{}{}
// Reset transient portions of the engine
// We start by clearing the event bus to
// remove most ongoing code
w.eventHandler.Reset()
// We follow by clearing collision areas
// because otherwise collision function calls
// on non-entities (i.e. particles) can still
// be triggered and attempt to access an entity
w.CollisionTree.Clear()
w.MouseTree.Clear()
w.CallerMap.Clear()
w.eventHandler.SetCallerMap(w.CallerMap)
w.DrawStack.Clear()
w.DrawStack.PreDraw()
// Todo: Add in customizable loading scene between regular scenes,
// In addition to the existing customizable loading renderable?
w.SceneMap.CurrentScene, result = scen.End()
if nextSceneOverride != "" {
w.SceneMap.CurrentScene = nextSceneOverride
}
// For convenience, we allow the user to return nil
// but it gets translated to an empty result
if result == nil {
result = new(scene.Result)
}
}
}