138 lines
4.0 KiB
Go
138 lines
4.0 KiB
Go
//go:build gl
|
||
|
||
// 设置界面(UI还原.md §2、UI与输入.md §6):
|
||
// 鼠标灵敏度 / 音量滑条 + 世界种子显示 + 按键教程列表 + 完成按钮。
|
||
// 滑条点击左/右半区为减/加;值由调用方持有并注入。
|
||
package ui
|
||
|
||
import (
|
||
"fmt"
|
||
)
|
||
|
||
// OptionsScreen 设置界面。
|
||
type OptionsScreen struct {
|
||
BtnTex uint32 // 原版按钮控件
|
||
BtnHover uint32
|
||
TitleTex uint32 // 「设置」标题
|
||
TitleW float32
|
||
TitleH float32
|
||
|
||
// CJK 标签与按键教程(构建时预光栅化)
|
||
SensLabelTex uint32
|
||
SensLabelW float32
|
||
SensLabelH float32
|
||
VolLabelTex uint32
|
||
VolLabelW float32
|
||
VolLabelH float32
|
||
ControlsTex uint32
|
||
ControlsW float32
|
||
ControlsH float32
|
||
SeedLabelTex uint32
|
||
SeedLabelW float32
|
||
SeedLabelH float32
|
||
DoneLabelTex uint32
|
||
DoneLabelW float32
|
||
DoneLabelH float32
|
||
|
||
ox float32 // 相对 1280 基准的水平偏移(窗口居中)
|
||
}
|
||
|
||
// 滑条区域(屏幕像素,1280×720 布局)。
|
||
var (
|
||
optSensBar = [4]float32{540, 260, 200, 10}
|
||
optVolBar = [4]float32{540, 330, 200, 10}
|
||
optDone = [4]float32{540, 560, 200, 20}
|
||
)
|
||
|
||
// Layout 按窗口宽度水平居中控件(相对 1280 基准)。
|
||
func (s *OptionsScreen) Layout(winW float32) {
|
||
s.ox = winW/2 - 640
|
||
}
|
||
|
||
func (s *OptionsScreen) bar(base [4]float32) [4]float32 {
|
||
return [4]float32{base[0] + s.ox, base[1], base[2], base[3]}
|
||
}
|
||
|
||
// HitTest 命中检测:返回 "sens-"/"sens+"/"vol-"/"vol+"/"done"/""。
|
||
func (s *OptionsScreen) HitTest(mx, my float32) string {
|
||
hit := func(r [4]float32) bool {
|
||
return mx >= r[0] && mx < r[0]+r[2] && my >= r[1] && my < r[1]+r[3]
|
||
}
|
||
sens := s.bar(optSensBar)
|
||
if hit(sens) {
|
||
if mx < sens[0]+sens[2]/2 {
|
||
return "sens-"
|
||
}
|
||
return "sens+"
|
||
}
|
||
vol := s.bar(optVolBar)
|
||
if hit(vol) {
|
||
if mx < vol[0]+vol[2]/2 {
|
||
return "vol-"
|
||
}
|
||
return "vol+"
|
||
}
|
||
if hit(s.bar(optDone)) {
|
||
return "done"
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// Draw 绘制设置界面(调用方已 Begin)。
|
||
func (s *OptionsScreen) Draw(r *Renderer, mx, my, sens, vol float32) {
|
||
w, h := float32(r.w), float32(r.h)
|
||
// 背景:土质暗色 + 标题
|
||
r.DrawRect(0, 0, w, h, [4]float32{0.10, 0.12, 0.10, 0.92})
|
||
if s.TitleTex != 0 {
|
||
r.pushQuad(quad{x: w/2 - s.TitleW/2, y: h * 0.10, w: s.TitleW, h: s.TitleH,
|
||
u0: 0, v0: 0, u1: 1, v1: 1, r: 1, g: 1, b: 1, a: 1, tex: s.TitleTex})
|
||
}
|
||
// 标签
|
||
s.blitLabel(r, s.SensLabelTex, s.SensLabelW, s.SensLabelH, 380+s.ox, 255)
|
||
s.blitLabel(r, s.VolLabelTex, s.VolLabelW, s.VolLabelH, 380+s.ox, 325)
|
||
// 滑条(底 + 填充 + 值)
|
||
s.drawSlider(r, s.bar(optSensBar), sens)
|
||
s.drawSlider(r, s.bar(optVolBar), vol)
|
||
// 世界种子
|
||
s.blitLabel(r, s.SeedLabelTex, s.SeedLabelW, s.SeedLabelH, 380+s.ox, 395)
|
||
// 按键教程列表
|
||
s.blitLabel(r, s.ControlsTex, s.ControlsW, s.ControlsH, 380+s.ox, 435)
|
||
// 完成按钮
|
||
done := s.bar(optDone)
|
||
hover := mx >= done[0] && mx < done[0]+done[2] && my >= done[1] && my < done[1]+done[3]
|
||
tex := s.BtnTex
|
||
if hover && s.BtnHover != 0 {
|
||
tex = s.BtnHover
|
||
}
|
||
if tex != 0 {
|
||
r.pushQuad(quad{x: done[0], y: done[1], w: done[2], h: done[3],
|
||
u0: 0, v0: 0, u1: 1, v1: 1, r: 1, g: 1, b: 1, a: 1, tex: tex})
|
||
}
|
||
if s.DoneLabelTex != 0 {
|
||
r.pushQuad(quad{x: done[0] + (done[2]-s.DoneLabelW)/2, y: done[1] + (done[3]-s.DoneLabelH)/2,
|
||
w: s.DoneLabelW, h: s.DoneLabelH, u0: 0, v0: 0, u1: 1, v1: 1,
|
||
r: 1, g: 1, b: 1, a: 1, tex: s.DoneLabelTex})
|
||
}
|
||
}
|
||
|
||
// drawSlider 绘制滑条:底轨 + 按比例填充 + 数值文本(0–1)。
|
||
func (s *OptionsScreen) drawSlider(r *Renderer, bar [4]float32, v float32) {
|
||
if v < 0 {
|
||
v = 0
|
||
}
|
||
if v > 1 {
|
||
v = 1
|
||
}
|
||
r.DrawRect(bar[0], bar[1], bar[2], bar[3], [4]float32{0.2, 0.2, 0.2, 1})
|
||
r.DrawRect(bar[0], bar[1], bar[2]*v, bar[3], [4]float32{0.4, 0.9, 0.4, 1})
|
||
r.DrawText(bar[0]+bar[2]+12, bar[1]-6, fmt.Sprintf("%.0f%%", v*100), 1, [4]float32{1, 1, 1, 1})
|
||
}
|
||
|
||
func (s *OptionsScreen) blitLabel(r *Renderer, tex uint32, w, h, x, y float32) {
|
||
if tex == 0 {
|
||
return
|
||
}
|
||
r.pushQuad(quad{x: x, y: y, w: w, h: h, u0: 0, v0: 0, u1: 1, v1: 1,
|
||
r: 1, g: 1, b: 1, a: 1, tex: tex})
|
||
}
|