292 lines
10 KiB
Go
292 lines
10 KiB
Go
package gallery
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"time"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
|
)
|
|
|
|
var controlEntries = []Entry{
|
|
{86, "Select", "下拉选择", "input", "The choice and ▼; the list opens in a window with a hand pointing. Arrows and Enter pick.", demoSelect},
|
|
{87, "MultiSelect", "多选", "input", "A popup of checkboxes; what you pick rides in the trigger as tags.", demoMultiSelect},
|
|
{88, "Combobox", "组合框", "input", "Type to narrow the list below; Enter or a click takes one.", demoCombobox},
|
|
{89, "Autocomplete", "自动补全", "input", "The rest of the word waits in grey. Tab or Enter takes it.", demoAutocomplete},
|
|
{90, "TokenField", "标记输入", "input", "Tags before the caret. Enter or a comma adds; Backspace on empty takes the last back.", demoTokenField},
|
|
{91, "Segmented", "分段控件", "input", "Joined segments, one lit. Arrows move the light.", demoSegmented},
|
|
{92, "Rating", "评分", "input", "Stars or hearts. Click or arrows to rate; click the same mark to clear.", demoRating},
|
|
{93, "Knob", "旋钮", "input", "A rotary knob that clicks through 16 angles. Drag up or down, or use the arrows.", demoKnob},
|
|
{94, "PinInput", "验证码", "input", "One box per digit: typing moves on, Backspace steps back, paste fills them all.", demoPinInput},
|
|
{95, "NameEntry", "姓名登记", "input", "HIGH SCORE! Three initials from the letter grid, then END.", demoNameEntry},
|
|
{96, "VirtualKeyboard", "屏幕键盘", "input", "A keyboard on screen, for pads and touch: letters, digits, space, erase, enter.", demoVirtualKeyboard},
|
|
{97, "DPad", "方向键", "input", "A cross pad. Press an arm or use the arrow keys.", demoDPad},
|
|
{98, "HoldButton", "长按按钮", "input", "Hold it down while the bar fills in eight steps. Let go and it starts over.", demoHoldButton},
|
|
{99, "EditableText", "可编辑文本", "input", "Double click or press Enter to rename. Enter keeps it; Escape takes it back.", demoEditableText},
|
|
{100, "Field", "表单项", "input", "A label above, a hint below, and a red ! when something is wrong.", demoField},
|
|
{101, "Fieldset", "字段组", "input", "A framed group of fields under a legend.", demoFieldset},
|
|
{102, "ColorSlot", "色槽选择", "input", "Pick one of the sixteen palette slots. It follows the palette.", demoColorSlot},
|
|
{103, "Joystick", "摇杆", "input", "Drag the stick inside its ring; it springs home. Arrows nudge it.", demoJoystick},
|
|
{104, "CheatCode", "秘籍", "input", "Focus it and enter ↑↑↓↓←→←→BA. You know the one.", demoCheatCode},
|
|
{105, "SlotPicker", "滚轮选择", "input", "Reels that spin by drag, wheel or arrows. Line up three for the jackpot.", demoSlotPicker},
|
|
}
|
|
|
|
type controlDemo struct {
|
|
class, item, spell, hero, call, guild string
|
|
party, tags []string
|
|
mode, banner, stars, lives int
|
|
reel1, reel2, reel3 int
|
|
volume, bass float64
|
|
pin, initials, message string
|
|
cape pixel.Slot
|
|
dir input.Direction
|
|
}
|
|
|
|
func controlState(c *ui.Context) *controlDemo {
|
|
return ui.Local(c.Root(), demoKey("controls"), func() controlDemo {
|
|
return controlDemo{class: "Knight", hero: "Pixel Knight", tags: []string{"retro", "pixel"}, mode: 1, stars: 4, lives: 3,
|
|
volume: 0.7, bass: 0.3, cape: pixel.Accent, reel2: 1, reel3: 2}
|
|
})
|
|
}
|
|
|
|
func demoSelect(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
if input.Select(c, "Class", &s.class, []string{"Knight", "Mage", "Thief", "Bard"}, input.SelectOptions{}).Changed {
|
|
log("class " + s.class)
|
|
}
|
|
}
|
|
|
|
func demoMultiSelect(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
if input.MultiSelect(c, "Party", &s.party, []string{"Warrior", "Healer", "Rogue", "Wizard"}, input.MultiSelectOptions{}).Changed {
|
|
log(fmt.Sprintf("party %v", s.party))
|
|
}
|
|
}
|
|
|
|
func demoCombobox(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
items := []string{"Potion", "Hi-Potion", "Ether", "Elixir", "Antidote", "Phoenix Down"}
|
|
r := input.Combobox(c, "Item", &s.item, items, input.ComboboxOptions{Placeholder: "Use an item…", Width: 140})
|
|
if r.Changed {
|
|
log("item " + s.item)
|
|
}
|
|
if r.Chosen {
|
|
log("used " + s.item)
|
|
}
|
|
}
|
|
|
|
func demoAutocomplete(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
spells := []string{"Fire", "Fira", "Firaga", "Blizzard", "Thunder", "Cure", "Curaga"}
|
|
r := input.Autocomplete(c, "Spell", &s.spell, spells, input.AutocompleteOptions{Placeholder: "Cast…"})
|
|
if r.Changed {
|
|
log("spell " + s.spell)
|
|
}
|
|
if r.Accepted {
|
|
log("cast " + s.spell)
|
|
}
|
|
if r.Submitted {
|
|
log("fizzle: " + s.spell)
|
|
}
|
|
}
|
|
|
|
func demoTokenField(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
if input.TokenField(c, "Tags", &s.tags, input.TokenFieldOptions{Placeholder: "add tag"}).Changed {
|
|
log(fmt.Sprintf("tags %v", s.tags))
|
|
}
|
|
}
|
|
|
|
func demoSegmented(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
modes := []string{"EASY", "NORMAL", "HARD"}
|
|
if input.Segmented(c, "Difficulty", modes, &s.mode, input.SegmentedOptions{}).Changed {
|
|
log("difficulty " + modes[s.mode])
|
|
}
|
|
}
|
|
|
|
func demoRating(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
s := controlState(c)
|
|
ui.Column(c).Gap(k.D(6)).Children(func() {
|
|
if input.Rating(c, "Dungeon", &s.stars, input.RatingOptions{}).Changed {
|
|
log(fmt.Sprintf("%d stars", s.stars))
|
|
}
|
|
if input.Rating(c, "Lives", &s.lives, input.RatingOptions{Max: 3, Hearts: true}).Changed {
|
|
log(fmt.Sprintf("%d lives", s.lives))
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoKnob(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
s := controlState(c)
|
|
ui.Row(c).Gap(k.D(12)).AlignItems(ui.Center).Children(func() {
|
|
for _, kn := range []struct {
|
|
name string
|
|
v *float64
|
|
}{{"VOL", &s.volume}, {"BASS", &s.bass}} {
|
|
ui.Column(c).Gap(k.D(2)).AlignItems(ui.Center).Children(func() {
|
|
if input.Knob(c, kn.name, kn.v, input.KnobOptions{Step: 0.05}).Changed {
|
|
log(fmt.Sprintf("%s %.2f", kn.name, *kn.v))
|
|
}
|
|
pixel.Text(c, fmt.Sprintf("%s %d", kn.name, int(*kn.v*100+0.5)), pixel.TextOptions{Slot: pixel.Faint})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoPinInput(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
r := input.PinInput(c, "Vault code", &s.pin, input.PinInputOptions{})
|
|
if r.Changed {
|
|
log(fmt.Sprintf("%d digits", len(s.pin)))
|
|
}
|
|
if r.Complete {
|
|
if s.pin == "0451" {
|
|
log("ACCESS GRANTED")
|
|
} else {
|
|
log("WRONG CODE " + s.pin)
|
|
}
|
|
}
|
|
}
|
|
|
|
func demoNameEntry(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
s := controlState(c)
|
|
ui.Column(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
|
pixel.Text(c, "NEW HIGH SCORE 99999", pixel.TextOptions{Slot: pixel.Accent})
|
|
r := input.NameEntry(c, "Initials", &s.initials, input.NameEntryOptions{})
|
|
if r.Changed {
|
|
log("initials " + s.initials)
|
|
}
|
|
if r.Confirmed {
|
|
log("1ST " + s.initials + " 99999")
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoVirtualKeyboard(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
r := input.VirtualKeyboard(c, "Message", &s.message, input.VirtualKeyboardOptions{})
|
|
if r.Changed {
|
|
log("message " + s.message)
|
|
}
|
|
if r.Submitted {
|
|
log("sent " + s.message)
|
|
s.message = ""
|
|
}
|
|
}
|
|
|
|
func demoDPad(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
s := controlState(c)
|
|
ui.Row(c).Gap(k.D(12)).AlignItems(ui.Center).Children(func() {
|
|
if d := input.DPad(c, "Pad", input.DPadOptions{}).Pressed; d != input.None {
|
|
s.dir = d
|
|
log(d.String())
|
|
}
|
|
pixel.Text(c, "last: "+s.dir.String(), pixel.TextOptions{Slot: pixel.Faint})
|
|
})
|
|
}
|
|
|
|
func demoHoldButton(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
ui.Row(c).Gap(k.D(6)).Children(func() {
|
|
if input.HoldButton(c, "SKIP CUTSCENE", input.HoldButtonOptions{}).Confirmed {
|
|
log("cutscene skipped")
|
|
}
|
|
if input.HoldButton(c, "DELETE SAVE", input.HoldButtonOptions{Duration: 2 * time.Second, Danger: true}).Confirmed {
|
|
log("save deleted (not really)")
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoEditableText(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
if input.EditableText(c, "Hero name", &s.hero, input.EditableTextOptions{Placeholder: "Nameless"}).Changed {
|
|
log("renamed to " + s.hero)
|
|
}
|
|
}
|
|
|
|
func demoField(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
o := input.FieldOptions{Description: "Shown on the leaderboard."}
|
|
if s.call == "" {
|
|
o.Error = "A hero needs a call sign!"
|
|
}
|
|
input.Field(c, "Call sign", o, func() {
|
|
r := input.TextInput(c, "Call sign", &s.call, input.TextInputOptions{MaxLength: 10})
|
|
if r.Changed {
|
|
log("call sign " + s.call)
|
|
}
|
|
if r.Submitted {
|
|
log("signed " + s.call)
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoFieldset(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
input.Fieldset(c, "Guild", input.FieldsetOptions{}, func() {
|
|
input.Field(c, "Name", input.FieldOptions{}, func() {
|
|
r := input.TextInput(c, "Guild name", &s.guild, input.TextInputOptions{Placeholder: "The Dot Matrix"})
|
|
if r.Changed {
|
|
log("guild " + s.guild)
|
|
}
|
|
if r.Submitted {
|
|
log("founded " + s.guild)
|
|
}
|
|
})
|
|
banners := []string{"RED", "BLUE", "GOLD"}
|
|
if input.Segmented(c, "Banner", banners, &s.banner, input.SegmentedOptions{}).Changed {
|
|
log("banner " + banners[s.banner])
|
|
}
|
|
})
|
|
}
|
|
|
|
func demoColorSlot(c *ui.Context, log func(string)) {
|
|
s := controlState(c)
|
|
if input.ColorSlot(c, "Cape", &s.cape, input.ColorSlotOptions{}).Changed {
|
|
log("cape " + s.cape.String())
|
|
}
|
|
}
|
|
|
|
func demoJoystick(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
ui.Row(c).Gap(k.D(12)).AlignItems(ui.Center).Children(func() {
|
|
r := input.Joystick(c, "Stick", input.JoystickOptions{})
|
|
if r.Moved {
|
|
log(fmt.Sprintf("x %+.2f y %+.2f", r.X, r.Y))
|
|
}
|
|
pixel.Text(c, fmt.Sprintf("X %+.2f Y %+.2f", r.X, r.Y), pixel.TextOptions{Slot: pixel.Faint})
|
|
})
|
|
}
|
|
|
|
func demoCheatCode(c *ui.Context, log func(string)) {
|
|
if input.CheatCode(c, "Cheat", input.CheatCodeOptions{}).Unlocked {
|
|
log("30 LIVES!")
|
|
}
|
|
}
|
|
|
|
func demoSlotPicker(c *ui.Context, log func(string)) {
|
|
k := pixel.K(c)
|
|
s := controlState(c)
|
|
fruit := []string{"Cherry", "Bell", "Seven", "Melon", "BAR"}
|
|
ui.Row(c).Gap(k.D(4)).Children(func() {
|
|
changed := false
|
|
for i, v := range []*int{&s.reel1, &s.reel2, &s.reel3} {
|
|
if input.SlotPicker(c, fmt.Sprintf("Reel %d", i+1), v, fruit, input.SlotPickerOptions{}).Changed {
|
|
changed = true
|
|
log(fmt.Sprintf("reel %d %s", i+1, fruit[*v]))
|
|
}
|
|
}
|
|
if all := []int{s.reel1, s.reel2, s.reel3}; changed && slices.Max(all) == slices.Min(all) {
|
|
log("JACKPOT! " + fruit[s.reel1])
|
|
}
|
|
})
|
|
}
|