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

mlange-42 / ark-pixel / 13719732838

07 Mar 2025 11:28AM CUT coverage: 29.148% (+8.1%) from 21.025%
13719732838

push

github

web-flow
Add entity inspector (#4)

76 of 103 new or added lines in 1 file covered. (73.79%)

195 of 669 relevant lines covered (29.15%)

31.42 hits per line

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

0.0
/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/ark-tools/app"
13
        "github.com/mlange-42/ark/ecs"
14
)
15

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

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

37
        if c.Scale <= 0 {
×
38
                c.Scale = 1
×
39
        }
×
40

41
        c.drawer = *imdraw.New(nil)
×
42
        c.text = text.New(px.V(0, 0), defaultFont)
×
43

44
}
45

46
// Update the drawer.
47
func (c *Controls) Update(w *ecs.World) {}
×
48

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

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

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

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

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

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

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

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

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

×
110
        dr.Draw(win)
×
111
        dr.Clear()
×
112

×
113
        c.text.Clear()
×
114
        fmt.Fprint(c.text, text)
×
115

×
116
        wTxt := c.text.Bounds().W()
×
117
        hTxt := c.text.Bounds().H()
×
118
        cx, cy := b.Center()
×
119
        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))))
×
120
}
×
121

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

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

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

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

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

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

169
func (b *button) Contains(x, y float64) bool {
×
170
        return x >= b.X && y >= b.Y && x <= b.X+b.W && y <= b.Y+b.H
×
171
}
×
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