124 lines
3.6 KiB
Go
124 lines
3.6 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
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 滑条区域(屏幕像素,1280×720 布局)。
|
|||
|
|
var (
|
|||
|
|
optSensBar = [4]float32{540, 260, 200, 10}
|
|||
|
|
optVolBar = [4]float32{540, 330, 200, 10}
|
|||
|
|
optDone = [4]float32{540, 560, 200, 20}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 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]
|
|||
|
|
}
|
|||
|
|
if hit(optSensBar) {
|
|||
|
|
if mx < optSensBar[0]+optSensBar[2]/2 {
|
|||
|
|
return "sens-"
|
|||
|
|
}
|
|||
|
|
return "sens+"
|
|||
|
|
}
|
|||
|
|
if hit(optVolBar) {
|
|||
|
|
if mx < optVolBar[0]+optVolBar[2]/2 {
|
|||
|
|
return "vol-"
|
|||
|
|
}
|
|||
|
|
return "vol+"
|
|||
|
|
}
|
|||
|
|
if hit(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, 255)
|
|||
|
|
s.blitLabel(r, s.VolLabelTex, s.VolLabelW, s.VolLabelH, 380, 325)
|
|||
|
|
// 滑条(底 + 填充 + 值)
|
|||
|
|
s.drawSlider(r, optSensBar, sens)
|
|||
|
|
s.drawSlider(r, optVolBar, vol)
|
|||
|
|
// 世界种子
|
|||
|
|
s.blitLabel(r, s.SeedLabelTex, s.SeedLabelW, s.SeedLabelH, 380, 395)
|
|||
|
|
// 按键教程列表
|
|||
|
|
s.blitLabel(r, s.ControlsTex, s.ControlsW, s.ControlsH, 380, 435)
|
|||
|
|
// 完成按钮
|
|||
|
|
hover := mx >= optDone[0] && mx < optDone[0]+optDone[2] && my >= optDone[1] && my < optDone[1]+optDone[3]
|
|||
|
|
tex := s.BtnTex
|
|||
|
|
if hover && s.BtnHover != 0 {
|
|||
|
|
tex = s.BtnHover
|
|||
|
|
}
|
|||
|
|
if tex != 0 {
|
|||
|
|
r.pushQuad(quad{x: optDone[0], y: optDone[1], w: optDone[2], h: optDone[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: optDone[0] + (optDone[2]-s.DoneLabelW)/2, y: optDone[1] + (optDone[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})
|
|||
|
|
}
|