• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / arche-pixel / 8971918437

06 May 2024 03:47PM CUT coverage: 88.232% (+0.02%) from 88.217%
8971918437

push

github

web-flow
Skip NaN values in `Lines` plot, allowing for partial lines (#52)

* Skip NaN values in `Lines` plot, allowing for partial lines
* Add a test with NaN values

2 of 2 new or added lines in 1 file covered. (100.0%)

1432 of 1623 relevant lines covered (88.23%)

222921.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.79
/plot/controls.go
1
package plot
2

3
import (
4
        "fmt"
5
        "image/color"
6
        "math"
7

8
        px "github.com/gopxl/pixel/v2"
9
        "github.com/gopxl/pixel/v2/backends/opengl"
10
        "github.com/gopxl/pixel/v2/ext/imdraw"
11
        "github.com/gopxl/pixel/v2/ext/text"
12
        "github.com/mlange-42/arche-model/model"
13
        "github.com/mlange-42/arche/ecs"
14
        "github.com/mlange-42/arche/generic"
15
)
16

17
// Controls adds UI and keyboard input for controlling the simulation.
18
// UI controls are displayed in the bottom right corner of the window.
19
//
20
// Pause and resume the simulation via a button or by pressing SPACE.
21
// Manipulate simulation speed (TPS) using buttons or UP/DOWN keys.
22
//
23
// Expects a world resource of type Systems ([github.com/mlange-42/arche-model/model.Systems]).
24
type Controls struct {
25
        Scale      float64 // Spatial scaling: cell size in screen pixels. Optional, default 1.
26
        drawer     imdraw.IMDraw
27
        systemsRes generic.Resource[model.Systems]
28
        text       *text.Text
29
}
30

31
// Initialize the system
32
func (c *Controls) Initialize(w *ecs.World, win *opengl.Window) {
3✔
33
        c.systemsRes = generic.NewResource[model.Systems](w)
3✔
34
        if !c.systemsRes.Has() {
3✔
35
                panic("resource of type Systems expected in Controls drawer")
×
36
        }
37

38
        if c.Scale <= 0 {
5✔
39
                c.Scale = 1
2✔
40
        }
2✔
41

42
        c.drawer = *imdraw.New(nil)
3✔
43
        c.text = text.New(px.V(0, 0), defaultFont)
3✔
44

45
}
46

47
// Update the drawer.
48
func (c *Controls) Update(w *ecs.World) {}
300✔
49

50
// UpdateInputs handles input events of the previous frame update.
51
func (c *Controls) UpdateInputs(w *ecs.World, win *opengl.Window) {
300✔
52
        sys := c.systemsRes.Get()
300✔
53
        if win.JustPressed(px.KeySpace) {
300✔
54
                sys.Paused = !sys.Paused
×
55
                return
×
56
        }
×
57
        if win.JustPressed(px.KeyUp) {
300✔
58
                sys.TPS = calcTps(sys.TPS, true)
×
59
                return
×
60
        }
×
61
        if win.JustPressed(px.KeyDown) {
300✔
62
                sys.TPS = calcTps(sys.TPS, false)
×
63
                return
×
64
        }
×
65

66
        if win.JustPressed(px.MouseButton1) {
300✔
67
                width := win.Canvas().Bounds().W()
×
68
                height := win.Canvas().Bounds().H()
×
69

×
70
                mouse := win.MousePosition()
×
71
                if c.pauseBounds(width, height).Contains(mouse.X, mouse.Y) {
×
72
                        sys.Paused = !sys.Paused
×
73
                } else if c.upButton(width, height).Contains(mouse.X, mouse.Y) {
×
74
                        sys.TPS = calcTps(sys.TPS, true)
×
75
                } else if c.downButton(width, height).Contains(mouse.X, mouse.Y) {
×
76
                        sys.TPS = calcTps(sys.TPS, false)
×
77
                }
×
78
        }
79
}
80

81
// Draw the system
82
func (c *Controls) Draw(w *ecs.World, win *opengl.Window) {
210✔
83
        width := win.Canvas().Bounds().W()
210✔
84
        height := win.Canvas().Bounds().H()
210✔
85

210✔
86
        sys := c.systemsRes.Get()
210✔
87
        text := "Pause"
210✔
88
        if sys.Paused {
210✔
89
                text = "Resume"
×
90
        }
×
91
        c.drawButton(c.pauseBounds(width, height), text, win)
210✔
92

210✔
93
        c.drawButton(c.upButton(width, height), "+", win)
210✔
94
        c.drawButton(c.downButton(width, height), "-", win)
210✔
95
        c.drawButton(c.tpsButton(width, height), fmt.Sprintf("%.0f TPS", sys.TPS), win)
210✔
96
}
97

98
func (c *Controls) drawButton(b *button, text string, win *opengl.Window) {
840✔
99
        dr := &c.drawer
840✔
100

840✔
101
        dr.Color = color.Black
840✔
102
        dr.Push(px.V(b.X, b.Y), px.V(b.X+b.W, b.Y+b.H))
840✔
103
        dr.Rectangle(0)
840✔
104
        dr.Reset()
840✔
105

840✔
106
        dr.Color = color.White
840✔
107
        dr.Push(px.V(b.X, b.Y), px.V(b.X+b.W, b.Y+b.H))
840✔
108
        dr.Rectangle(1)
840✔
109
        dr.Reset()
840✔
110

840✔
111
        dr.Draw(win)
840✔
112
        dr.Clear()
840✔
113

840✔
114
        c.text.Clear()
840✔
115
        fmt.Fprint(c.text, text)
840✔
116

840✔
117
        wTxt := c.text.Bounds().W()
840✔
118
        hTxt := c.text.Bounds().H()
840✔
119
        cx, cy := b.Center()
840✔
120
        c.text.Draw(win, px.IM.Scaled(px.V(wTxt/2, hTxt/2), c.Scale).Moved(px.V(math.Floor(cx-wTxt/2), math.Floor(cy-hTxt/2))))
840✔
121
}
840✔
122

123
func (c *Controls) pauseBounds(w, h float64) *button {
210✔
124
        return &button{
210✔
125
                w - 85*c.Scale,
210✔
126
                5 + 15*c.Scale,
210✔
127
                60 * c.Scale,
210✔
128
                30 * c.Scale,
210✔
129
        }
210✔
130
}
210✔
131

132
func (c *Controls) upButton(w, h float64) *button {
210✔
133
        return &button{
210✔
134
                w - 25*c.Scale,
210✔
135
                5 + 30*c.Scale,
210✔
136
                20 * c.Scale,
210✔
137
                15 * c.Scale,
210✔
138
        }
210✔
139
}
210✔
140

141
func (c *Controls) downButton(w, h float64) *button {
210✔
142
        return &button{
210✔
143
                w - 25*c.Scale,
210✔
144
                5 + 15*c.Scale,
210✔
145
                20 * c.Scale,
210✔
146
                15 * c.Scale,
210✔
147
        }
210✔
148
}
210✔
149

150
func (c *Controls) tpsButton(w, h float64) *button {
210✔
151
        return &button{
210✔
152
                w - 85*c.Scale,
210✔
153
                5,
210✔
154
                80 * c.Scale,
210✔
155
                15 * c.Scale,
210✔
156
        }
210✔
157
}
210✔
158

159
type button struct {
160
        X float64
161
        Y float64
162
        W float64
163
        H float64
164
}
165

166
func (b *button) Center() (float64, float64) {
840✔
167
        return b.X + b.W/2, b.Y + b.H/2
840✔
168
}
840✔
169

170
func (b *button) Contains(x, y float64) bool {
×
171
        return x >= b.X && y >= b.Y && x <= b.X+b.W && y <= b.Y+b.H
×
172
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc