274 lines
10 KiB
Go
274 lines
10 KiB
Go
package gallery
|
||
|
||
import (
|
||
"fmt"
|
||
"image"
|
||
"image/color"
|
||
"math"
|
||
|
||
"github.com/egoist/mygo/ui"
|
||
|
||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/display"
|
||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||
)
|
||
|
||
var displayEntries = []Entry{
|
||
{41, "Icon", "图标", "display", "A sprite in one ink slot at ×1 to ×4, named for screen readers or hidden.", demoIcon},
|
||
{42, "Sprite", "精灵", "display", "A multi-slot sprite that plays its frames and can face the other way.", demoSprite},
|
||
{43, "Picture", "像素图", "display", "Any image reduced to the palette with Bayer dither. Press P: it recolors.", demoPicture},
|
||
{44, "Avatar", "头像", "display", "A face built from a name: skin, hair, eyes, mouth and background.", demoAvatar},
|
||
{45, "AvatarGroup", "头像组", "display", "Overlapping faces and a chip for the rest.", demoAvatarGroup},
|
||
{46, "Badge", "徽标", "display", "A count or a word in a notched pill; counts stop at 99+.", demoBadge},
|
||
{47, "Tag", "标签", "display", "A chip with text, an icon and a remove box.", demoTag},
|
||
{48, "StatusDot", "状态点", "display", "Online, away, busy or offline; a live online dot blinks.", demoStatusDot},
|
||
{49, "Medal", "奖牌", "display", "Gold, silver and bronze on ribbons, rank on the face.", demoMedal},
|
||
{50, "Trophy", "奖杯", "display", "A gold cup over an engraved plaque.", demoTrophy},
|
||
{51, "Stat", "数据", "display", "A big value, its label and a change up or down.", demoStat},
|
||
{52, "KeyValue", "键值", "display", "A label and a value joined by a dotted leader.", demoKeyValue},
|
||
{53, "Portrait", "立绘框", "display", "A character in a frame over a nameplate.", demoPortrait},
|
||
{54, "Ribbon", "绶带", "display", "A title banner with folded, notched tails.", demoRibbon},
|
||
{55, "Stamp", "印章", "display", "A rubber stamp whose border wore unevenly.", demoStamp},
|
||
{56, "Emoji", "表情", "display", "Sixteen faces placed dot by dot.", demoEmoji},
|
||
{57, "Flag", "旗帜", "display", "A flag on a pole, waving in steps.", demoFlag},
|
||
{58, "Gem", "宝石", "display", "A cut gem for each rarity, with a stepped sparkle.", demoGem},
|
||
{59, "RarityFrame", "稀有度框", "display", "A border by rarity; a legendary one carries a running glint.", demoRarityFrame},
|
||
{60, "Bubble", "气泡", "display", "A speech bubble with its tail on any side.", demoBubble},
|
||
{61, "Swatch", "色板", "display", "The sixteen slots of the palette in use, by name.", demoSwatch},
|
||
{62, "Placeholder", "占位图", "display", "A dithered box with a cross and its size, for art to come.", demoPlaceholder},
|
||
{63, "Figure", "插图", "display", "Content over a caption in Faint.", demoFigure},
|
||
{64, "QRCode", "二维码", "display", "A scannable QR code in the darkest and lightest slots.", demoQRCode},
|
||
{65, "Signpost", "路牌", "display", "A post with up to three boards. Each board is a button.", demoSignpost},
|
||
}
|
||
|
||
// sunset is a smooth picture for Picture to reduce.
|
||
var sunset = func() image.Image {
|
||
img := image.NewRGBA(image.Rect(0, 0, 96, 64))
|
||
for y := range 64 {
|
||
for x := range 96 {
|
||
t := float64(y) / 63
|
||
c := color.RGBA{uint8(250 - 120*t), uint8(170 - 120*t), uint8(90 + 90*t), 255}
|
||
if dx, dy := float64(x-60), float64(y-34); dx*dx+dy*dy < 14*14 {
|
||
c = color.RGBA{255, 220, 120, 255}
|
||
}
|
||
if float64(y) > 44+6*math.Sin(float64(x)/9) {
|
||
c = color.RGBA{50, 40, 70, 255}
|
||
}
|
||
img.SetRGBA(x, y, c)
|
||
}
|
||
}
|
||
return img
|
||
}()
|
||
|
||
func demoIcon(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.End).Children(func() {
|
||
for sc := 1; sc <= 4; sc++ {
|
||
display.Icon(c, icon.Heart, display.IconOptions{Slot: pixel.Bad, Scale: sc, Label: fmt.Sprintf("heart ×%d", sc)})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoSprite(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(12)).Children(func() {
|
||
display.Sprite(c, slime, display.SpriteOptions{Scale: 3, FPS: 2, Label: "slime"})
|
||
display.Sprite(c, slime, display.SpriteOptions{Scale: 3, FPS: 2, Mirror: true, Label: "slime, mirrored"})
|
||
})
|
||
}
|
||
|
||
func demoPicture(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.End).Children(func() {
|
||
display.Picture(c, sunset, display.PictureOptions{Label: "sunset"})
|
||
display.Picture(c, sunset, display.PictureOptions{W: 48, H: 32, Label: "small sunset"})
|
||
})
|
||
}
|
||
|
||
var party = []string{"Aria", "Brom", "Cass", "Dax", "Eve", "Finn", "Gus"}
|
||
|
||
func demoAvatar(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(6)).Children(func() {
|
||
for _, n := range party[:5] {
|
||
display.Avatar(c, n, display.AvatarOptions{Scale: 2})
|
||
}
|
||
display.Avatar(c, "Sunny", display.AvatarOptions{Scale: 2, Picture: sunset})
|
||
})
|
||
}
|
||
|
||
func demoAvatarGroup(c *ui.Context, log func(string)) {
|
||
display.AvatarGroup(c, party, display.AvatarGroupOptions{Scale: 2})
|
||
}
|
||
|
||
func demoBadge(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||
for _, n := range []int{3, 42, 128} {
|
||
display.Badge(c, n, display.BadgeOptions{})
|
||
}
|
||
display.Badge(c, 0, display.BadgeOptions{Text: "NEW", Slot: pixel.Good})
|
||
display.Badge(c, 0, display.BadgeOptions{Text: "HOT", Slot: pixel.Warn})
|
||
})
|
||
}
|
||
|
||
func demoTag(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
tags := ui.Local(c.Root(), demoKey("tags"), func() []string { return []string{"fire", "ice", "thunder", "wind"} })
|
||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||
ui.Row(c).Wrap().Gap(k.D(4)).Children(func() {
|
||
for i, t := range *tags {
|
||
if display.Tag(c, t, display.TagOptions{Icon: icon.Sparkle, Removable: true}).Removed {
|
||
*tags = append((*tags)[:i:i], (*tags)[i+1:]...)
|
||
log("removed " + t)
|
||
}
|
||
}
|
||
display.Tag(c, "locked", display.TagOptions{Icon: icon.Lock, Removable: true, Disabled: true})
|
||
})
|
||
if input.Button(c, "RESET", input.ButtonOptions{}).Clicked {
|
||
*tags = []string{"fire", "ice", "thunder", "wind"}
|
||
log("tags reset")
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoStatusDot(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Column(c).Gap(k.D(4)).Children(func() {
|
||
for _, s := range []display.Status{display.Online, display.Away, display.Busy, display.Offline} {
|
||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
||
display.StatusDot(c, s, display.StatusDotOptions{Live: true})
|
||
pixel.Text(c, []string{"Player 1", "Player 2", "Player 3", "Player 4"}[s], pixel.TextOptions{})
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoMedal(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(10)).Children(func() {
|
||
for _, r := range []display.Rank{display.Gold, display.Silver, display.Bronze} {
|
||
display.Medal(c, r, display.MedalOptions{Scale: 2})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoTrophy(c *ui.Context, log func(string)) {
|
||
display.Trophy(c, "Champion 2026", display.TrophyOptions{Scale: 2})
|
||
}
|
||
|
||
func demoStat(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(24)).Children(func() {
|
||
display.Stat(c, "SCORE", "42,000", display.StatOptions{Delta: "12%"})
|
||
display.Stat(c, "LIVES", "2", display.StatOptions{Delta: "1", Down: true})
|
||
})
|
||
}
|
||
|
||
func demoKeyValue(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Column(c).Width(k.D(160)).Gap(k.D(2)).Children(func() {
|
||
for _, kv := range [][2]string{{"STR", "18"}, {"DEX", "12"}, {"INT", "7"}, {"LUCK", "99"}} {
|
||
display.KeyValue(c, kv[0], kv[1], display.KeyValueOptions{})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoPortrait(c *ui.Context, log func(string)) {
|
||
display.Portrait(c, "Sir Brom", display.PortraitOptions{Size: 48}, func() {
|
||
display.Avatar(c, "Brom", display.AvatarOptions{Scale: 3})
|
||
})
|
||
}
|
||
|
||
func demoRibbon(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||
display.Ribbon(c, "STAGE 1-1", display.RibbonOptions{})
|
||
display.Ribbon(c, "BONUS ROUND", display.RibbonOptions{Slot: pixel.Info})
|
||
})
|
||
}
|
||
|
||
func demoStamp(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(10)).Children(func() {
|
||
display.Stamp(c, "APPROVED", display.StampOptions{Slot: pixel.Good, Seed: 3})
|
||
display.Stamp(c, "VOID", display.StampOptions{Seed: 9})
|
||
})
|
||
}
|
||
|
||
func demoEmoji(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Wrap().Gap(k.D(6)).Width(k.D(240)).Children(func() {
|
||
for _, name := range display.EmojiNames {
|
||
display.Emoji(c, name, display.EmojiOptions{Scale: 2})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoFlag(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(12)).Children(func() {
|
||
display.Flag(c, display.FlagOptions{Scale: 2, Label: "red flag"})
|
||
display.Flag(c, display.FlagOptions{Slot: pixel.Info, Scale: 2, Label: "blue flag"})
|
||
})
|
||
}
|
||
|
||
func demoGem(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(8)).Children(func() {
|
||
for r := display.Common; r <= display.Legendary; r++ {
|
||
display.Gem(c, r, display.GemOptions{Scale: 2})
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoRarityFrame(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
items := []string{"Stick", "Bow", "Rapier", "Dragon Lance", "Excalibur"}
|
||
ui.Row(c).Wrap().Gap(k.D(6)).Children(func() {
|
||
for r := display.Common; r <= display.Legendary; r++ {
|
||
display.RarityFrame(c, r, display.RarityFrameOptions{}, func() { pixel.Text(c, items[r], pixel.TextOptions{}) })
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoBubble(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
lines := []string{"Hey!", "Look up.", "Psst.", "Over here."}
|
||
ui.Row(c).Wrap().Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||
for i, side := range []display.Side{display.Bottom, display.Top, display.Left, display.Right} {
|
||
display.Bubble(c, display.BubbleOptions{Tail: side}, func() { pixel.Text(c, lines[i], pixel.TextOptions{}) })
|
||
}
|
||
})
|
||
}
|
||
|
||
func demoSwatch(c *ui.Context, log func(string)) {
|
||
display.Swatch(c, display.SwatchOptions{})
|
||
}
|
||
|
||
func demoPlaceholder(c *ui.Context, log func(string)) {
|
||
k := pixel.K(c)
|
||
ui.Row(c).Gap(k.D(8)).Children(func() {
|
||
display.Placeholder(c, display.PlaceholderOptions{})
|
||
display.Placeholder(c, display.PlaceholderOptions{W: 120, H: 40})
|
||
})
|
||
}
|
||
|
||
func demoFigure(c *ui.Context, log func(string)) {
|
||
display.Figure(c, "Fig. 1 — a slime, at rest", display.FigureOptions{}, func() {
|
||
display.Sprite(c, slime, display.SpriteOptions{Scale: 4, Label: "slime"})
|
||
})
|
||
}
|
||
|
||
func demoQRCode(c *ui.Context, log func(string)) {
|
||
display.QRCode(c, "https://mygo.egoist.dev/docs/ui", display.QRCodeOptions{})
|
||
}
|
||
|
||
func demoSignpost(c *ui.Context, log func(string)) {
|
||
boards := []string{"Town", "Dungeon", "Shop"}
|
||
if r := display.Signpost(c, boards, display.SignpostOptions{}); r.Clicked >= 0 {
|
||
log("to the " + boards[r.Clicked])
|
||
}
|
||
}
|