Files
ngzz-mc/internal/ui/screens.go

134 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build gl
// 界面屏幕:主菜单与暂停菜单(UI还原.md §2:布局/控件/版本角标复刻原版)。
package ui
// Button 一个按钮:区域 + 悬停高亮 + 标签纹理。
type Button struct {
X, Y, W, H float32
Tex uint32 // 标签纹理(预光栅化中文)
LabelW float32
LabelH float32
Action string
}
// TitleScreen 主菜单(UI还原.md §2:土质背景 + 标题 + 原版按钮 + 版本/版权角标)。
type TitleScreen struct {
TitleTex uint32
TitleW float32
TitleH float32
SplashTex uint32 // 黄色 splash 文本(原版风格)
SplashW float32
SplashH float32
BgTex uint32 // 土质背景(16px dirt 平铺预渲染)
BtnTex uint32 // 原版按钮控件(widget/button.png 200×20)
BtnHover uint32 // 悬停高亮(button_highlighted.png)
Buttons []Button
Version string // 左下角版本(原版角标)
Copyright string // 右下角版权
}
// HitTest 命中检测(按钮区域)。
func (s *TitleScreen) HitTest(mx, my float32) string {
for _, b := range s.Buttons {
if mx >= b.X && mx <= b.X+b.W && my >= b.Y && my <= b.Y+b.H {
return b.Action
}
}
return ""
}
// Draw 绘制主菜单(原版布局:背景 → 标题+splash → 按钮列 → 版本/版权角标)。
func (s *TitleScreen) Draw(r *Renderer, mx, my float32) {
w, h := float32(r.w), float32(r.h)
// 土质背景(UI还原.md §2 背景)
if s.BgTex != 0 {
r.pushQuad(quad{x: 0, y: 0, w: w, h: h, u0: 0, v0: 0, u1: 1, v1: 1,
r: 1, g: 1, b: 1, a: 1, tex: s.BgTex})
} else {
r.DrawRect(0, 0, w, h, [4]float32{0.08, 0.1, 0.12, 1})
}
// 标题(居中偏上,原版 logo 位置)
if s.TitleTex != 0 {
r.pushQuad(quad{x: w/2 - s.TitleW/2, y: h * 0.15, 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})
}
// splash(标题右下,原版黄色倾斜文本——MVP 水平放置)
if s.SplashTex != 0 {
r.pushQuad(quad{x: w/2 + s.TitleW/2 - s.SplashW + 20, y: h*0.15 + s.TitleH, w: s.SplashW, h: s.SplashH,
u0: 0, v0: 0, u1: 1, v1: 1, r: 1, g: 1, b: 1, a: 1, tex: s.SplashTex})
}
// 按钮列(原版:居中偏下,200×20 控件 + 标签)
for _, b := range s.Buttons {
hover := mx >= b.X && mx <= b.X+b.W && my >= b.Y && my <= b.Y+b.H
tex := s.BtnTex
if hover && s.BtnHover != 0 {
tex = s.BtnHover
}
if tex != 0 {
r.pushQuad(quad{x: b.X, y: b.Y, w: b.W, h: b.H, u0: 0, v0: 0, u1: 1, v1: 1,
r: 1, g: 1, b: 1, a: 1, tex: tex})
}
if b.Tex != 0 {
// 标签居中
r.pushQuad(quad{x: b.X + (b.W-b.LabelW)/2, y: b.Y + (b.H-b.LabelH)/2, w: b.LabelW, h: b.LabelH,
u0: 0, v0: 0, u1: 1, v1: 1, r: 1, g: 1, b: 1, a: 1, tex: b.Tex})
}
}
// 版本角标(左下)与版权(右下,原版样式)
if s.Version != "" {
r.DrawText(8, h-12, s.Version, 1, [4]float32{1, 1, 1, 1})
}
if s.Copyright != "" {
r.DrawText(w-r.TextWidth(s.Copyright, 1)-8, h-12, s.Copyright, 1, [4]float32{1, 1, 1, 1})
}
}
// PauseScreen 暂停菜单(UI还原.md §2:半透明遮罩 + 原版按钮)。
type PauseScreen struct {
TitleTex uint32
TitleW float32
TitleH float32
BtnTex uint32
BtnHover uint32
Buttons []Button
}
// HitTest 命中检测。
func (s *PauseScreen) HitTest(mx, my float32) string {
for _, b := range s.Buttons {
if mx >= b.X && mx <= b.X+b.W && my >= b.Y && my <= b.Y+b.H {
return b.Action
}
}
return ""
}
// Draw 绘制暂停菜单。
func (s *PauseScreen) Draw(r *Renderer, mx, my float32) {
w, h := float32(r.w), float32(r.h)
r.DrawRect(0, 0, w, h, [4]float32{0, 0, 0, 0.6})
if s.TitleTex != 0 {
r.pushQuad(quad{x: w/2 - s.TitleW/2, y: h * 0.15, 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})
}
for _, b := range s.Buttons {
hover := mx >= b.X && mx <= b.X+b.W && my >= b.Y && my <= b.Y+b.H
tex := s.BtnTex
if hover && s.BtnHover != 0 {
tex = s.BtnHover
}
if tex != 0 {
r.pushQuad(quad{x: b.X, y: b.Y, w: b.W, h: b.H, u0: 0, v0: 0, u1: 1, v1: 1,
r: 1, g: 1, b: 1, a: 1, tex: tex})
}
if b.Tex != 0 {
r.pushQuad(quad{x: b.X + (b.W-b.LabelW)/2, y: b.Y + (b.H-b.LabelH)/2, w: b.LabelW, h: b.LabelH,
u0: 0, v0: 0, u1: 1, v1: 1, r: 1, g: 1, b: 1, a: 1, tex: b.Tex})
}
}
}