-
Notifications
You must be signed in to change notification settings - Fork 84
/
lifecycle.go
130 lines (111 loc) · 3.35 KB
/
lifecycle.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
package oak
import (
"image"
"image/draw"
"sync"
"github.com/oakmound/oak/alg"
"github.com/oakmound/oak/dlog"
"github.com/oakmound/oak/event"
"golang.org/x/exp/shiny/screen"
)
var (
winBuffer screen.Buffer
screenControl screen.Screen
windowControl screen.Window
windowRect image.Rectangle
windowUpdateCh = make(chan bool)
initControl = sync.Mutex{}
lifecycleInit bool
)
func lifecycleLoop(s screen.Screen) {
initControl.Lock()
if lifecycleInit {
dlog.Error("Started lifecycle twice, aborting second call")
initControl.Unlock()
return
}
lifecycleInit = true
initControl.Unlock()
dlog.Info("Init Lifecycle")
screenControl = s
var err error
// The window buffer represents the subsection of the world which is available to
// be shown in a window.
dlog.Info("Creating window buffer")
winBuffer, err = screenControl.NewBuffer(image.Point{ScreenWidth, ScreenHeight})
if err != nil {
dlog.Error(err)
return
}
// The window controller handles incoming hardware or platform events and
// publishes image data to the screen.\
dlog.Info("Creating window controller")
changeWindow(ScreenWidth*conf.Screen.Scale, ScreenHeight*conf.Screen.Scale)
dlog.Info("Getting event bus")
eb = event.GetBus()
dlog.Info("Starting draw loop")
go drawLoop()
dlog.Info("Starting input loop")
go inputLoop()
dlog.Info("Starting event handler")
go event.ResolvePending()
// The quit channel represents a signal
// for the engine to stop.
<-quitCh
}
func changeWindow(width, height int) {
// The window controller handles incoming hardware or platform events and
// publishes image data to the screen.
wC, err := windowController(screenControl, width, height)
if err != nil {
dlog.Error(err)
panic(err)
}
windowControl = wC
ChangeWindow(width, height)
}
var (
// UseAspectRatio determines whether new window changes will distort or
// maintain the relative width to height ratio of the screen buffer.
UseAspectRatio = false
aspectRatio float64
)
// SetAspectRatio will enforce that the displayed window does not distort the
// input screen away from the given x:y ratio. The screen will not use these
// settings until a new size event is received from the OS.
func SetAspectRatio(xToY float64) {
UseAspectRatio = true
aspectRatio = xToY
}
// ChangeWindow sets the width and height of the game window. Although exported,
// calling it without a size event will probably not act as expected.
func ChangeWindow(width, height int) {
// Draw a black frame to cover up smears
// Todo: could restrict the black to -just- the area not covered by the
// scaled screen buffer
buff, err := screenControl.NewBuffer(image.Point{width, height})
if err == nil {
draw.Draw(buff.RGBA(), buff.Bounds(), imageBlack, zeroPoint, screen.Src)
windowControl.Upload(zeroPoint, buff, buff.Bounds())
} else {
dlog.Error(err)
}
var x, y int
if UseAspectRatio {
inRatio := float64(width) / float64(height)
if aspectRatio > inRatio {
newHeight := alg.RoundF64(float64(height) * (inRatio / aspectRatio))
y = (newHeight - height) / 2
height = newHeight - y
} else {
newWidth := alg.RoundF64(float64(width) * (aspectRatio / inRatio))
x = (newWidth - width) / 2
width = newWidth - x
}
}
windowRect = image.Rect(-x, -y, width, height)
}
// GetScreen returns the current screen as an rgba buffer
func GetScreen() *image.RGBA {
return winBuffer.RGBA()
}