mirror of
https://github.com/libretro/ludo.git
synced 2026-11-08 01:04:34 -10:00
Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ba89b41d0 | ||
|
|
7791c486da | ||
|
|
a66883f1c7 | ||
|
|
cdb0eca4ef | ||
|
|
906ff44765 | ||
|
|
c36cabda18 | ||
|
|
5329d5f1bc | ||
|
|
a397aa304a | ||
|
|
d8ebaaf204 | ||
|
|
0404944e4e | ||
|
|
cf257d243f | ||
|
|
a92eb01727 | ||
|
|
fe23690446 | ||
|
|
69e3efe4b2 | ||
|
|
9b696af388 | ||
|
|
356d645b67 | ||
|
|
987493bcc5 |
No files matched your search
+32
-8
@@ -5,14 +5,38 @@ import (
|
||||
"github.com/libretro/ludo/input"
|
||||
)
|
||||
|
||||
// Used to easily compose different hint bars based on the context.
|
||||
func stackHint(stack *float32, icon uint32, label string, h int) {
|
||||
vid.Font.SetColor(darkGrey)
|
||||
*stack += 30 * menu.ratio
|
||||
vid.DrawImage(icon, *stack, float32(h)-70*menu.ratio, 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
*stack += 70 * menu.ratio
|
||||
vid.Font.Printf(*stack, float32(h)-23*menu.ratio, 0.4*menu.ratio, label)
|
||||
*stack += vid.Font.Width(0.4*menu.ratio, label)
|
||||
// HintBar is the bar showing at the bottom of the screen
|
||||
func HintBar(props *Props, children ...func()) func() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
return HBox(&Props{
|
||||
Y: float32(h) - 70*menu.ratio,
|
||||
Width: float32(w),
|
||||
Height: 70 * menu.ratio,
|
||||
Color: lightGrey,
|
||||
Hidden: props.Hidden,
|
||||
},
|
||||
children...,
|
||||
)
|
||||
}
|
||||
|
||||
// Hint is a widget combining an icon and a label
|
||||
func Hint(props *Props, icon uint32, title string) func() {
|
||||
darkGrey := darkGrey
|
||||
return HBox(props,
|
||||
Box(&Props{Width: 15}),
|
||||
Image(&Props{
|
||||
Width: 70 * menu.ratio,
|
||||
Height: 70 * menu.ratio,
|
||||
Scale: 1,
|
||||
Color: darkGrey,
|
||||
}, icon),
|
||||
Label(&Props{
|
||||
Height: 70 * menu.ratio,
|
||||
Scale: 0.4 * menu.ratio,
|
||||
Color: darkGrey,
|
||||
}, title),
|
||||
Box(&Props{Width: 15}),
|
||||
)
|
||||
}
|
||||
|
||||
func hintIcons() (arrows, upDown, leftRight, a, b, x, y, start, slct, guide uint32) {
|
||||
|
||||
+35
-26
@@ -23,32 +23,41 @@ var severityBgColor = map[ntf.Severity]video.Color{
|
||||
func (m *Menu) RenderNotifications() {
|
||||
fbw, fbh := vid.Window.GetFramebufferSize()
|
||||
vid.Font.UpdateResolution(fbw, fbh)
|
||||
var h float32 = 75
|
||||
stack := h
|
||||
stack := float32(0)
|
||||
for _, n := range ntf.List() {
|
||||
fading := n.Duration * 4
|
||||
if fading > 1 {
|
||||
fading = 1
|
||||
}
|
||||
offset := fading*h - h
|
||||
lw := vid.Font.Width(0.5*m.ratio, n.Message)
|
||||
fg := severityFgColor[n.Severity]
|
||||
bg := severityBgColor[n.Severity]
|
||||
vid.DrawRect(
|
||||
25*m.ratio,
|
||||
(stack+offset-46)*m.ratio,
|
||||
lw+40*m.ratio,
|
||||
70*m.ratio,
|
||||
0.25,
|
||||
bg.Alpha(fading),
|
||||
)
|
||||
vid.Font.SetColor(fg.Alpha(fading))
|
||||
vid.Font.Printf(
|
||||
45*m.ratio,
|
||||
(stack+offset)*m.ratio,
|
||||
0.5*m.ratio,
|
||||
n.Message,
|
||||
)
|
||||
stack += h + offset
|
||||
offset := minf32(n.Duration*4, 1) * 80
|
||||
lw := vid.Font.Width(0.4*menu.ratio, n.Message)
|
||||
|
||||
Toast(&Props{
|
||||
X: 25 * menu.ratio,
|
||||
Y: (stack + offset - 80 + 25) * menu.ratio,
|
||||
Width: lw + 70*menu.ratio + 20*menu.ratio,
|
||||
Height: 70 * menu.ratio,
|
||||
BorderRadius: 0.25,
|
||||
}, n)()
|
||||
|
||||
stack += offset
|
||||
}
|
||||
}
|
||||
|
||||
// Toast can render a notification
|
||||
func Toast(props *Props, n *ntf.Notification) func() {
|
||||
alpha := minf32(n.Duration*4, 1)
|
||||
fg := severityFgColor[n.Severity].Alpha(alpha)
|
||||
bg := severityBgColor[n.Severity].Alpha(alpha)
|
||||
props.Color = bg
|
||||
|
||||
return HBox(props,
|
||||
Image(&Props{
|
||||
Width: props.Height,
|
||||
Height: props.Height,
|
||||
Scale: 1,
|
||||
Color: fg,
|
||||
}, menu.icons["core-infos"]),
|
||||
Label(&Props{
|
||||
Height: props.Height,
|
||||
Scale: 0.4 * menu.ratio,
|
||||
Color: fg,
|
||||
}, n.Message),
|
||||
)
|
||||
}
|
||||
+7
-13
@@ -174,6 +174,7 @@ func thumbnailDrawCursor(list *entry) {
|
||||
// It also display values of settings if we are displaying a settings scene
|
||||
func genericRender(list *entry) {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
fontOffset := 64 * 0.7 * menu.ratio * 0.3
|
||||
|
||||
genericDrawCursor(list)
|
||||
|
||||
@@ -184,8 +185,6 @@ func genericRender(list *entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
fontOffset := 64 * 0.7 * menu.ratio * 0.3
|
||||
|
||||
vid.DrawImage(menu.icons[e.icon],
|
||||
610*menu.ratio-64*0.5*menu.ratio,
|
||||
float32(h)*e.yp-14*menu.ratio-64*0.5*menu.ratio+fontOffset,
|
||||
@@ -215,16 +214,11 @@ func genericRender(list *entry) {
|
||||
}
|
||||
|
||||
func genericDrawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
stackHint(&stack, a, "OK", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{}, a, "OK"),
|
||||
)()
|
||||
}
|
||||
@@ -80,16 +80,11 @@ func (s *sceneCoreOptions) render() {
|
||||
}
|
||||
|
||||
func (s *sceneCoreOptions) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
stackHint(&stack, leftRight, "SET", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{}, leftRight, "SET"),
|
||||
)()
|
||||
}
|
||||
+42
-49
@@ -50,59 +50,52 @@ func (s *sceneDialog) render() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
fw := float32(w)
|
||||
fh := float32(h)
|
||||
vid.DrawRect(0, 0, fw, fh, 0, black.Alpha(0.85))
|
||||
|
||||
var width float32 = 1000
|
||||
var height float32 = 400
|
||||
|
||||
vid.DrawRect(
|
||||
fw/2-width/2*menu.ratio,
|
||||
fh/2-height/2*menu.ratio,
|
||||
width*menu.ratio,
|
||||
height*menu.ratio,
|
||||
0.05,
|
||||
white,
|
||||
)
|
||||
|
||||
vid.Font.SetColor(orange)
|
||||
msg1 := "A game is currently running."
|
||||
lw1 := vid.Font.Width(0.7*menu.ratio, msg1)
|
||||
vid.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio+20*menu.ratio, 0.7*menu.ratio, msg1)
|
||||
vid.Font.SetColor(black)
|
||||
msg2 := "If you have not saved yet, your progress will be lost."
|
||||
lw2 := vid.Font.Width(0.5*menu.ratio, msg2)
|
||||
vid.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg2)
|
||||
msg3 := "Do you want to exit Ludo anyway?"
|
||||
lw3 := vid.Font.Width(0.5*menu.ratio, msg3)
|
||||
vid.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, msg3)
|
||||
|
||||
vid.Font.SetColor(darkGrey)
|
||||
|
||||
var margin float32 = 15
|
||||
width := 1000 * menu.ratio
|
||||
height := 400 * menu.ratio
|
||||
|
||||
_, _, _, a, b, _, _, _, _, _ := hintIcons()
|
||||
|
||||
vid.DrawImage(
|
||||
b,
|
||||
fw/2-width/2*menu.ratio+margin*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio,
|
||||
70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
vid.Font.Printf(
|
||||
fw/2-width/2*menu.ratio+margin*menu.ratio+70*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio,
|
||||
0.4*menu.ratio,
|
||||
"NO")
|
||||
|
||||
vid.DrawImage(
|
||||
a,
|
||||
fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio,
|
||||
70*menu.ratio, 70*menu.ratio, 1.0, darkGrey)
|
||||
vid.Font.Printf(
|
||||
fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio+70*menu.ratio,
|
||||
fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio,
|
||||
0.4*menu.ratio,
|
||||
"YES")
|
||||
// Background
|
||||
Box(&Props{Width: fw, Height: fh, Color: black.Alpha(0.85)},
|
||||
// Dialog
|
||||
VBox(&Props{
|
||||
X: fw/2 - width/2,
|
||||
Y: fh/2 - height/2,
|
||||
Width: width,
|
||||
Height: height,
|
||||
BorderRadius: 0.05,
|
||||
Color: white,
|
||||
},
|
||||
// Title
|
||||
Label(&Props{
|
||||
TextAlign: "center",
|
||||
Scale: 0.7 * menu.ratio,
|
||||
Color: orange,
|
||||
Height: 150 * menu.ratio,
|
||||
}, "A game is currently running"),
|
||||
// Messages
|
||||
Label(&Props{
|
||||
TextAlign: "center",
|
||||
Scale: 0.5 * menu.ratio,
|
||||
Color: black,
|
||||
Height: 60 * menu.ratio,
|
||||
}, "If you have not saved yet, your progress will be lost."),
|
||||
Label(&Props{
|
||||
TextAlign: "center",
|
||||
Scale: 0.5 * menu.ratio,
|
||||
Color: black,
|
||||
Height: 60 * menu.ratio,
|
||||
}, "Do you want to exit Ludo anyway?"),
|
||||
Box(&Props{Height: 40 * menu.ratio}),
|
||||
Box(&Props{},
|
||||
// The NO Hint
|
||||
Hint(&Props{}, b, "NO"),
|
||||
// The YES Hint
|
||||
Hint(&Props{X: width - 175*menu.ratio}, a, "YES"),
|
||||
),
|
||||
),
|
||||
)()
|
||||
}
|
||||
|
||||
func (s *sceneDialog) drawHintBar() {
|
||||
|
||||
+6
-11
@@ -189,16 +189,11 @@ func (s *sceneHistory) render() {
|
||||
}
|
||||
|
||||
func (s *sceneHistory) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
stackHint(&stack, a, "RUN", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{}, a, "RUN"),
|
||||
)()
|
||||
}
|
||||
+8
-11
@@ -204,16 +204,13 @@ func (s *sceneKeyboard) render() {
|
||||
}
|
||||
|
||||
func (s *sceneKeyboard) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
arrows, _, _, a, b, x, y, start, _, _ := hintIcons()
|
||||
|
||||
var stack float32
|
||||
stackHint(&stack, arrows, "SELECT", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
stackHint(&stack, x, "SHIFT", h)
|
||||
stackHint(&stack, y, "DELETE", h)
|
||||
stackHint(&stack, a, "INSERT", h)
|
||||
stackHint(&stack, start, "DONE", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{}, arrows, "SELECT"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{}, x, "SHIFT"),
|
||||
Hint(&Props{}, y, "DELETE"),
|
||||
Hint(&Props{}, a, "INSERT"),
|
||||
Hint(&Props{}, start, "DONE"),
|
||||
)()
|
||||
}
|
||||
+6
-11
@@ -210,16 +210,11 @@ func (s *scenePlaylist) render() {
|
||||
}
|
||||
|
||||
func (s *scenePlaylist) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
stackHint(&stack, a, "RUN", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{}, a, "RUN"),
|
||||
)()
|
||||
}
|
||||
@@ -135,22 +135,13 @@ func (s *sceneSavestates) render() {
|
||||
}
|
||||
|
||||
func (s *sceneSavestates) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
ptr := menu.stack[len(menu.stack)-1].Entry().ptr
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
if ptr == 0 {
|
||||
stackHint(&stack, a, "SAVE", h)
|
||||
} else {
|
||||
stackHint(&stack, a, "LOAD", h)
|
||||
}
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{Hidden: ptr != 0}, a, "SAVE"),
|
||||
Hint(&Props{Hidden: ptr == 0}, a, "LOAD"),
|
||||
)()
|
||||
}
|
||||
+8
-16
@@ -260,21 +260,13 @@ func (s *sceneSettings) render() {
|
||||
}
|
||||
|
||||
func (s *sceneSettings) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
cb := s.children[s.ptr].callbackOK
|
||||
_, upDown, leftRight, a, b, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
list := menu.stack[len(menu.stack)-1].Entry()
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
if list.children[list.ptr].callbackOK != nil {
|
||||
stackHint(&stack, a, "SET", h)
|
||||
} else {
|
||||
stackHint(&stack, leftRight, "SET", h)
|
||||
}
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{Hidden: cb == nil}, a, "SET"),
|
||||
Hint(&Props{Hidden: cb != nil}, leftRight, "SET"),
|
||||
)()
|
||||
}
|
||||
+51
-34
@@ -256,47 +256,64 @@ func (tabs *sceneTabs) update(dt float32) {
|
||||
}
|
||||
}
|
||||
|
||||
// Tab is a widget that draws the homepage hexagon plus title
|
||||
func Tab(props *Props, i int, e entry) func() {
|
||||
c := colorful.Hcl(float64(i)*20, 0.5, 0.5)
|
||||
return Box(props,
|
||||
Box(&Props{Width: e.width * menu.ratio},
|
||||
Image(&Props{
|
||||
X: e.width/2*menu.ratio - 220*e.scale*menu.ratio,
|
||||
Y: -220 * e.scale * menu.ratio,
|
||||
Width: 440 * menu.ratio,
|
||||
Height: 440 * menu.ratio,
|
||||
Scale: e.scale,
|
||||
Color: video.Color{R: float32(c.R), G: float32(c.B), B: float32(c.G), A: e.iconAlpha},
|
||||
}, menu.icons["hexagon"]),
|
||||
Image(&Props{
|
||||
X: e.width/2*menu.ratio - 128*e.scale*menu.ratio,
|
||||
Y: -128 * e.scale * menu.ratio,
|
||||
Width: 256 * menu.ratio,
|
||||
Height: 256 * menu.ratio,
|
||||
Scale: e.scale,
|
||||
Color: video.Color{R: 1, G: 1, B: 1, A: e.iconAlpha},
|
||||
}, menu.icons[e.icon]),
|
||||
Label(&Props{
|
||||
Y: 250 * menu.ratio,
|
||||
TextAlign: "center",
|
||||
Scale: 0.6 * menu.ratio,
|
||||
Color: video.Color{R: float32(c.R), G: float32(c.B), B: float32(c.G), A: e.labelAlpha},
|
||||
}, e.label),
|
||||
Label(&Props{
|
||||
Y: 330 * menu.ratio,
|
||||
TextAlign: "center",
|
||||
Scale: 0.4 * menu.ratio,
|
||||
Color: video.Color{R: float32(c.R), G: float32(c.B), B: float32(c.G), A: e.labelAlpha},
|
||||
}, e.subLabel),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (tabs sceneTabs) render() {
|
||||
_, h := vid.Window.GetFramebufferSize()
|
||||
|
||||
stackWidth := 710 * menu.ratio
|
||||
var children []func()
|
||||
for i, e := range tabs.children {
|
||||
|
||||
cf := colorful.Hcl(float64(i)*20, 0.5, 0.5)
|
||||
c := video.Color{R: float32(cf.R), G: float32(cf.B), B: float32(cf.G), A: e.iconAlpha}
|
||||
|
||||
x := -menu.scroll*menu.ratio + stackWidth + e.width/2*menu.ratio
|
||||
|
||||
stackWidth += e.width*menu.ratio + e.margin*menu.ratio
|
||||
|
||||
if e.labelAlpha > 0 {
|
||||
vid.Font.SetColor(c.Alpha(e.labelAlpha))
|
||||
lw := vid.Font.Width(0.5*menu.ratio, e.label)
|
||||
vid.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio)), 0.5*menu.ratio, e.label)
|
||||
lw = vid.Font.Width(0.4*menu.ratio, e.subLabel)
|
||||
vid.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio)), 0.4*menu.ratio, e.subLabel)
|
||||
}
|
||||
|
||||
vid.DrawImage(menu.icons["hexagon"],
|
||||
x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio,
|
||||
440*menu.ratio, 440*menu.ratio, e.scale, c)
|
||||
|
||||
vid.DrawImage(menu.icons[e.icon],
|
||||
x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio,
|
||||
256*menu.ratio, 256*menu.ratio, e.scale, white.Alpha(e.iconAlpha))
|
||||
children = append(children, Tab(&Props{
|
||||
Y: float32(h) / 2,
|
||||
Width: e.width*menu.ratio + e.margin*menu.ratio,
|
||||
}, i, e))
|
||||
}
|
||||
|
||||
HBox(&Props{
|
||||
X: 710*menu.ratio - menu.scroll*menu.ratio,
|
||||
}, children...)()
|
||||
}
|
||||
|
||||
func (tabs sceneTabs) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, _, leftRight, a, _, _, _, _, _, guide := hintIcons()
|
||||
|
||||
var stack float32
|
||||
if state.Global.CoreRunning {
|
||||
stackHint(&stack, guide, "RESUME", h)
|
||||
}
|
||||
stackHint(&stack, leftRight, "NAVIGATE", h)
|
||||
stackHint(&stack, a, "OPEN", h)
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{Hidden: !state.Global.CoreRunning}, guide, "RESUME"),
|
||||
Hint(&Props{}, leftRight, "NAVIGATE"),
|
||||
Hint(&Props{}, a, "OPEN"),
|
||||
)()
|
||||
}
|
||||
+5
-10
@@ -85,15 +85,10 @@ func (s *sceneWiFi) render() {
|
||||
}
|
||||
|
||||
func (s *sceneWiFi) drawHintBar() {
|
||||
w, h := vid.Window.GetFramebufferSize()
|
||||
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey)
|
||||
|
||||
_, upDown, _, a, b, _, _, _, _, _ := hintIcons()
|
||||
|
||||
var stack float32
|
||||
stackHint(&stack, upDown, "NAVIGATE", h)
|
||||
stackHint(&stack, b, "BACK", h)
|
||||
if s.children[0].callbackOK != nil {
|
||||
stackHint(&stack, a, "CONNECT", h)
|
||||
}
|
||||
HintBar(&Props{},
|
||||
Hint(&Props{}, upDown, "NAVIGATE"),
|
||||
Hint(&Props{}, b, "BACK"),
|
||||
Hint(&Props{Hidden: s.children[0].callbackOK == nil}, a, "CONNECT"),
|
||||
)()
|
||||
}
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
package menu
|
||||
|
||||
import (
|
||||
"github.com/libretro/ludo/video"
|
||||
)
|
||||
|
||||
// Direction of the children widgets in a container
|
||||
type Direction uint8
|
||||
|
||||
const (
|
||||
// Vertical means that the children will stack on top of each others
|
||||
Vertical Direction = iota
|
||||
// Horizontal means that the children will stack from left to right
|
||||
Horizontal
|
||||
)
|
||||
|
||||
// Props are the properties of a widget
|
||||
type Props struct {
|
||||
X, Y float32
|
||||
Width, Height float32
|
||||
BorderRadius float32
|
||||
Scale float32
|
||||
TextAlign string
|
||||
ContentWidth float32
|
||||
ContentHeight float32
|
||||
Direction Direction
|
||||
Color video.Color
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
type propsStack []*Props
|
||||
|
||||
func (s *propsStack) Push(v *Props) *propsStack {
|
||||
*s = append(*s, v)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *propsStack) Pop() {
|
||||
l := len(*s)
|
||||
*s = (*s)[:l-1]
|
||||
}
|
||||
|
||||
func (s *propsStack) Last() *Props {
|
||||
if len(*s) == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*s)[len(*s)-1]
|
||||
}
|
||||
|
||||
func (s *propsStack) Sum() *Props {
|
||||
sum := Props{}
|
||||
for _, t := range *s {
|
||||
sum.X += t.X
|
||||
sum.Y += t.Y
|
||||
}
|
||||
return &sum
|
||||
}
|
||||
|
||||
var wStack = &propsStack{}
|
||||
var tStack = &propsStack{}
|
||||
|
||||
// Box is a basic widget container
|
||||
func Box(props *Props, children ...func()) func() {
|
||||
return func() {
|
||||
if props.Hidden {
|
||||
return
|
||||
}
|
||||
parent := wStack.Last()
|
||||
self := wStack.Push(props).Last()
|
||||
tsum := tStack.Push(&Props{}).Sum()
|
||||
sum := wStack.Sum()
|
||||
vid.DrawRect(sum.X+tsum.X, sum.Y+tsum.Y, props.Width, props.Height, props.BorderRadius, props.Color)
|
||||
for _, child := range children {
|
||||
child()
|
||||
}
|
||||
updateParent(parent, maxf32(props.Width, self.ContentWidth), maxf32(props.Height, self.ContentHeight))
|
||||
tStack.Pop()
|
||||
wStack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// HBox is an horizontal widget container
|
||||
func HBox(props *Props, children ...func()) func() {
|
||||
return func() {
|
||||
if props.Hidden {
|
||||
return
|
||||
}
|
||||
props.Direction = Horizontal
|
||||
parent := wStack.Last()
|
||||
self := wStack.Push(props).Last()
|
||||
tsum := tStack.Push(&Props{}).Sum()
|
||||
sum := wStack.Sum()
|
||||
vid.DrawRect(sum.X+tsum.X, sum.Y+tsum.Y, props.Width, props.Height, props.BorderRadius, props.Color)
|
||||
for _, child := range children {
|
||||
tStack.Push(&Props{X: wStack.Last().ContentWidth})
|
||||
child()
|
||||
tStack.Pop()
|
||||
}
|
||||
updateParent(parent, maxf32(props.Width, self.ContentWidth), maxf32(props.Height, self.ContentHeight))
|
||||
tStack.Pop()
|
||||
wStack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// VBox is a vertical widget container
|
||||
func VBox(props *Props, children ...func()) func() {
|
||||
return func() {
|
||||
if props.Hidden {
|
||||
return
|
||||
}
|
||||
props.Direction = Vertical
|
||||
parent := wStack.Last()
|
||||
self := wStack.Push(props).Last()
|
||||
tsum := tStack.Push(&Props{}).Sum()
|
||||
sum := wStack.Sum()
|
||||
vid.DrawRect(sum.X+tsum.X, sum.Y+tsum.Y, props.Width, props.Height, props.BorderRadius, props.Color)
|
||||
for _, child := range children {
|
||||
tStack.Push(&Props{Y: wStack.Last().ContentHeight})
|
||||
child()
|
||||
tStack.Pop()
|
||||
}
|
||||
updateParent(parent, maxf32(props.Width, self.ContentWidth), maxf32(props.Height, self.ContentHeight))
|
||||
tStack.Pop()
|
||||
wStack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// Label a widget is used to draw some text
|
||||
func Label(props *Props, msg string) func() {
|
||||
return func() {
|
||||
if props.Hidden || props.Color.A == 0 {
|
||||
return
|
||||
}
|
||||
parent := wStack.Last()
|
||||
self := wStack.Push(props).Last()
|
||||
tsum := tStack.Push(&Props{}).Sum()
|
||||
sum := wStack.Sum()
|
||||
vid.Font.SetColor(props.Color)
|
||||
textWidth := vid.Font.Width(props.Scale, msg)
|
||||
switch props.TextAlign {
|
||||
case "center":
|
||||
vid.Font.Printf(sum.X+tsum.X+parent.Width/2-textWidth/2, sum.Y+tsum.Y+self.Height*0.67, props.Scale, msg)
|
||||
default:
|
||||
vid.Font.Printf(sum.X+tsum.X, sum.Y+tsum.Y+self.Height*0.67, props.Scale, msg)
|
||||
}
|
||||
updateParent(parent, textWidth, maxf32(props.Height, self.ContentHeight))
|
||||
tStack.Pop()
|
||||
wStack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// Image is a widget used to display an image
|
||||
func Image(props *Props, image uint32) func() {
|
||||
return func() {
|
||||
if props.Hidden {
|
||||
return
|
||||
}
|
||||
parent := wStack.Last()
|
||||
sum := wStack.Push(props).Sum()
|
||||
tsum := tStack.Push(&Props{}).Sum()
|
||||
vid.DrawImage(image, sum.X+tsum.X, sum.Y+tsum.Y, props.Width, props.Height, props.Scale, props.Color)
|
||||
updateParent(parent, props.Width, props.Height)
|
||||
tStack.Pop()
|
||||
wStack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
func updateParent(parent *Props, w, h float32) {
|
||||
if parent != nil {
|
||||
switch parent.Direction {
|
||||
case Horizontal:
|
||||
parent.ContentWidth += w
|
||||
case Vertical:
|
||||
parent.ContentHeight += h
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func maxf32(a, b float32) float32 {
|
||||
if b > a {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func minf32(a, b float32) float32 {
|
||||
if b < a {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
Reference in new issue
Block a user