Spit and polish
UI improvements specifically for mobile (running the game with the `-w mobile` or `-w landscape` options) screen sizes. * Rework the Settings window to be mobile friendly to landscape oriented screens (`doodle -w landscape`) and migrate Options tab to magicform. * The toolbar in the Editor will be a single column of buttons on small screens, such as `-w mobile` (375x812) portrait mode smartphone. On larger screens the toolbar shows in two columns of buttons. * Fix tooltips not drawing on top. * Centralize the hard-coded references to specific font filenames * Add cheat code: `test load screen` to bring a sample loading screen up for a few seconds. It needs improvement on `-w landscape`
This commit is contained in:
parent
77297fd60d
commit
44122d4130
|
@ -31,4 +31,5 @@ var (
|
|||
CheatPlayAsThief = "play as thief"
|
||||
CheatPlayAsAnvil = "megaton weight"
|
||||
CheatGodMode = "god mode"
|
||||
CheatDebugLoadScreen = "test load screen"
|
||||
)
|
||||
|
|
|
@ -16,7 +16,7 @@ var (
|
|||
***************/
|
||||
|
||||
// Debug overlay (FPS etc.) settings.
|
||||
DebugFontFilename = "DejaVuSans-Bold.ttf"
|
||||
DebugFontFilename = SansBoldFont
|
||||
DebugFontSize = 16
|
||||
DebugLabelColor = render.MustHexColor("#FF9900")
|
||||
DebugValueColor = render.MustHexColor("#00CCFF")
|
||||
|
|
9
pkg/balance/fonts.go
Normal file
9
pkg/balance/fonts.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package balance
|
||||
|
||||
// Font filenames used as part of game configuration.
|
||||
const (
|
||||
// Main UI fonts (sans-serif and monospace)
|
||||
SansSerifFont = "DejaVuSans.ttf"
|
||||
MonospaceFont = "DejaVuSansMono.ttf"
|
||||
SansBoldFont = "DejaVuSans-Bold.ttf"
|
||||
)
|
|
@ -61,7 +61,7 @@ var (
|
|||
|
||||
// Default font filename selected for Text Tool in the editor.
|
||||
// TODO: better centralize font filenames, here and in theme.go
|
||||
TextToolDefaultFont = "DejaVuSans.ttf"
|
||||
TextToolDefaultFont = SansSerifFont
|
||||
|
||||
// Interval for auto-save in the editor
|
||||
AutoSaveInterval = 5 * time.Minute
|
||||
|
|
|
@ -4,7 +4,7 @@ import "git.kirsle.net/go/render"
|
|||
|
||||
// Shell related variables.
|
||||
var (
|
||||
ShellFontFilename = "DejaVuSansMono.ttf"
|
||||
ShellFontFilename = MonospaceFont
|
||||
ShellBackgroundColor = render.RGBA(0, 20, 40, 200)
|
||||
ShellForegroundColor = render.RGBA(0, 153, 255, 255)
|
||||
ShellPromptColor = render.White
|
||||
|
|
|
@ -23,7 +23,7 @@ var (
|
|||
Shadow: render.Black,
|
||||
}
|
||||
TitleScreenSubtitleFont = render.Text{
|
||||
FontFilename: "DejaVuSans.ttf",
|
||||
FontFilename: SansSerifFont,
|
||||
Size: 18,
|
||||
Color: render.SkyBlue,
|
||||
Shadow: render.SkyBlue.Darken(128),
|
||||
|
@ -44,7 +44,7 @@ var (
|
|||
Shadow: render.Black,
|
||||
}
|
||||
LoadScreenSecondaryFont = render.Text{
|
||||
FontFilename: "DejaVuSans.ttf",
|
||||
FontFilename: SansSerifFont,
|
||||
Size: 18,
|
||||
Color: render.SkyBlue,
|
||||
Shadow: render.SkyBlue.Darken(128),
|
||||
|
@ -54,7 +54,7 @@ var (
|
|||
|
||||
// Play Mode Touch UI Hints Font
|
||||
TouchHintsFont = render.Text{
|
||||
FontFilename: "DejaVuSans.ttf",
|
||||
FontFilename: SansSerifFont,
|
||||
Size: 14,
|
||||
Color: render.SkyBlue,
|
||||
Shadow: render.SkyBlue.Darken(128),
|
||||
|
@ -69,7 +69,7 @@ var (
|
|||
OutlineColor: render.Black,
|
||||
}
|
||||
TitleFont = render.Text{
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: SansBoldFont,
|
||||
Size: 9,
|
||||
Padding: 4,
|
||||
Color: render.White,
|
||||
|
@ -99,7 +99,7 @@ var (
|
|||
PadX: 4,
|
||||
}
|
||||
MenuFontBold = render.Text{
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: SansBoldFont,
|
||||
Size: 12,
|
||||
PadX: 4,
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ var (
|
|||
// LabelFont is the font for strong labels in UI.
|
||||
LabelFont = render.Text{
|
||||
Size: 12,
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: SansBoldFont,
|
||||
Padding: 4,
|
||||
Color: render.Black,
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ var (
|
|||
|
||||
LargeLabelFont = render.Text{
|
||||
Size: 18,
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: SansBoldFont,
|
||||
Padding: 4,
|
||||
Color: render.Black,
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ var (
|
|||
SmallMonoFont = render.Text{
|
||||
Size: 14,
|
||||
PadX: 3,
|
||||
FontFilename: "DejaVuSansMono.ttf",
|
||||
FontFilename: MonospaceFont,
|
||||
Color: render.Black,
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ var (
|
|||
CodeLiteralFont = render.Text{
|
||||
Size: 11,
|
||||
PadX: 3,
|
||||
FontFilename: "DejaVuSansMono.ttf",
|
||||
FontFilename: MonospaceFont,
|
||||
Color: render.Magenta,
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ var (
|
|||
LinkAnimSpeed uint64 = 30 // ticks
|
||||
|
||||
PlayButtonFont = render.Text{
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: SansBoldFont,
|
||||
Size: 16,
|
||||
Padding: 4,
|
||||
Color: render.RGBA(255, 255, 0, 255),
|
||||
|
@ -194,7 +194,7 @@ var (
|
|||
|
||||
// In-game level timer font.
|
||||
TimerFont = render.Text{
|
||||
FontFilename: "DejaVuSansMono.ttf",
|
||||
FontFilename: MonospaceFont,
|
||||
Size: 16,
|
||||
Color: render.Cyan,
|
||||
Stroke: render.DarkCyan,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package doodle
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/modal/loadscreen"
|
||||
)
|
||||
|
||||
// IsDefaultPlayerCharacter checks whether the DefaultPlayerCharacter doodad has
|
||||
|
@ -146,6 +149,18 @@ func (c Command) cheatCommand(d *Doodle) bool {
|
|||
d.FlashError("Use this cheat in Play Mode to toggle invincibility.")
|
||||
}
|
||||
|
||||
case balance.CheatDebugLoadScreen:
|
||||
loadscreen.ShowWithProgress()
|
||||
loadscreen.SetSubtitle("Loading: /dev/null", "Loadscreen testing.")
|
||||
go func() {
|
||||
var i float64
|
||||
for i = 0; i < 100; i++ {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
loadscreen.SetProgress(i / 100)
|
||||
}
|
||||
loadscreen.Hide()
|
||||
}()
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -53,8 +53,16 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
// We can draw 2 buttons per row, but for very small screens
|
||||
// e.g. mobile in portrait orientation, draw 1 button per row.
|
||||
buttonsPerRow = 1
|
||||
if isHoz || d.width >= enum.ScreenWidthSmall {
|
||||
buttonsPerRow = 2
|
||||
if isHoz {
|
||||
if d.width < enum.ScreenWidthSmall {
|
||||
// Narrow screens
|
||||
buttonsPerRow = 2
|
||||
}
|
||||
} else {
|
||||
if d.width >= enum.ScreenWidthSmall {
|
||||
// Screen wider than 600px = can spare room for 2 buttons per row.
|
||||
buttonsPerRow = 2
|
||||
}
|
||||
}
|
||||
|
||||
// Compute toolbar size to accommodate all buttons (+10 for borders/padding)
|
||||
|
@ -229,10 +237,11 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
})
|
||||
u.Supervisor.Add(btn)
|
||||
|
||||
ui.NewTooltip(btn, ui.Tooltip{
|
||||
tt := ui.NewTooltip(btn, ui.Tooltip{
|
||||
Text: button.Tooltip,
|
||||
Edge: tooltipEdge,
|
||||
})
|
||||
tt.Supervise(u.Supervisor)
|
||||
|
||||
btnRow.Pack(btn, btnPack)
|
||||
}
|
||||
|
@ -352,13 +361,22 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
Text: button.Label,
|
||||
Font: balance.SmallMonoFont,
|
||||
}))
|
||||
btn.SetBorderSize(1)
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
button.F()
|
||||
return nil
|
||||
})
|
||||
u.Supervisor.Add(btn)
|
||||
|
||||
// Which side to pack on?
|
||||
var side = ui.W
|
||||
if !isHoz && buttonsPerRow == 1 {
|
||||
// Vertical layout w/ narrow one-button-per-row, the +-
|
||||
// buttons stick out so stack them vertically.
|
||||
side = ui.S
|
||||
}
|
||||
sizeBtnFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
Side: side,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ func (s *MainScene) Setup(d *Doodle) error {
|
|||
s.updateButton = ui.NewButton("Update Button", ui.NewLabel(ui.Label{
|
||||
Text: "An update is available!",
|
||||
Font: render.Text{
|
||||
FontFilename: "DejaVuSans-Bold.ttf",
|
||||
FontFilename: balance.SansBoldFont,
|
||||
Size: 16,
|
||||
Color: render.Blue,
|
||||
Padding: 4,
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/ui"
|
||||
"git.kirsle.net/go/ui/style"
|
||||
|
@ -21,6 +22,7 @@ const (
|
|||
Checkbox
|
||||
Radiobox
|
||||
Selectbox
|
||||
Color
|
||||
)
|
||||
|
||||
// Form configuration.
|
||||
|
@ -61,11 +63,12 @@ type Field struct {
|
|||
Frame *ui.Frame
|
||||
|
||||
// Variable bindings, the type may infer to be:
|
||||
BoolVariable *bool // Checkbox
|
||||
TextVariable *string // Textbox
|
||||
IntVariable *int // Textbox
|
||||
Options []Option // Selectbox
|
||||
SelectValue interface{} // Selectbox default choice
|
||||
BoolVariable *bool // Checkbox
|
||||
TextVariable *string // Textbox
|
||||
IntVariable *int // Textbox
|
||||
Options []Option // Selectbox
|
||||
SelectValue interface{} // Selectbox default choice
|
||||
Color *render.Color // Color
|
||||
|
||||
// Tooltip to add to a form control.
|
||||
// Checkbox only for now.
|
||||
|
@ -181,6 +184,77 @@ func (form Form) Create(into *ui.Frame, fields []Field) {
|
|||
})
|
||||
}
|
||||
|
||||
// Color picker button.
|
||||
if row.Type == Color && row.Color != nil {
|
||||
btn := ui.NewButton("ColorPicker", ui.NewLabel(ui.Label{
|
||||
Text: " ",
|
||||
Font: row.Font,
|
||||
}))
|
||||
style := style.DefaultButton
|
||||
style.Background = *row.Color
|
||||
style.HoverBackground = style.Background.Lighten(20)
|
||||
btn.SetStyle(&style)
|
||||
|
||||
form.Supervisor.Add(btn)
|
||||
frame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
FillX: true,
|
||||
Expand: true,
|
||||
})
|
||||
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
// Open a ColorPicker widget.
|
||||
picker, err := ui.NewColorPicker(ui.ColorPicker{
|
||||
Title: "Select a color",
|
||||
Supervisor: form.Supervisor,
|
||||
Engine: form.Engine,
|
||||
Color: *row.Color,
|
||||
OnManualInput: func(callback func(render.Color)) {
|
||||
// Prompt the user to enter a hex color using the developer shell.
|
||||
shmem.Prompt("New color in hex notation: ", func(answer string) {
|
||||
if answer != "" {
|
||||
// XXX: pure white renders as invisible, fudge it a bit.
|
||||
if answer == "FFFFFF" {
|
||||
answer = "FFFFFE"
|
||||
}
|
||||
|
||||
color, err := render.HexColor(answer)
|
||||
if err != nil {
|
||||
shmem.Flash("Error with that color code: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Reconfigure the button now.
|
||||
style.Background = color
|
||||
style.HoverBackground = style.Background.Lighten(20)
|
||||
|
||||
callback(color)
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Couldn't open ColorPicker: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
picker.Then(func(color render.Color) {
|
||||
*row.Color = color
|
||||
style.Background = color
|
||||
style.HoverBackground = style.Background.Lighten(20)
|
||||
|
||||
// call onClick to save change to disk now
|
||||
if row.OnClick != nil {
|
||||
row.OnClick()
|
||||
}
|
||||
})
|
||||
|
||||
picker.Center(shmem.CurrentRenderEngine.WindowSize())
|
||||
picker.Show()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Buttons and Text fields (for now).
|
||||
if row.Type == Button || row.Type == Textbox {
|
||||
btn := ui.NewButton("Button", ui.NewLabel(ui.Label{
|
||||
|
@ -198,7 +272,8 @@ func (form Form) Create(into *ui.Frame, fields []Field) {
|
|||
|
||||
// Tooltip? TODO - make nicer.
|
||||
if row.Tooltip.Text != "" || row.Tooltip.TextVariable != nil {
|
||||
ui.NewTooltip(btn, row.Tooltip)
|
||||
tt := ui.NewTooltip(btn, row.Tooltip)
|
||||
tt.Supervise(form.Supervisor)
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
@ -224,7 +299,8 @@ func (form Form) Create(into *ui.Frame, fields []Field) {
|
|||
|
||||
// Tooltip? TODO - make nicer.
|
||||
if row.Tooltip.Text != "" || row.Tooltip.TextVariable != nil {
|
||||
ui.NewTooltip(cb, row.Tooltip)
|
||||
tt := ui.NewTooltip(cb, row.Tooltip)
|
||||
tt.Supervise(form.Supervisor)
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
|
|
@ -244,10 +244,11 @@ func makeDoodadTab(config DoodadDropper, frame *ui.Frame, size render.Rect, cate
|
|||
})
|
||||
|
||||
// Tooltip hover to show the doodad's name.
|
||||
ui.NewTooltip(btn, ui.Tooltip{
|
||||
tt := ui.NewTooltip(btn, ui.Tooltip{
|
||||
Text: doodad.Title,
|
||||
Edge: ui.Top,
|
||||
})
|
||||
tt.Supervise(config.Supervisor)
|
||||
|
||||
// Begin the drag event to grab this Doodad.
|
||||
// NOTE: The drag target is the EditorUI.Canvas in
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
package windows
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/gamepad"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/native"
|
||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||
magicform "git.kirsle.net/apps/doodle/pkg/uix/magic-form"
|
||||
"git.kirsle.net/apps/doodle/pkg/usercfg"
|
||||
"git.kirsle.net/apps/doodle/pkg/userdir"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/ui"
|
||||
"git.kirsle.net/go/ui/style"
|
||||
)
|
||||
|
||||
// Settings window.
|
||||
|
@ -61,7 +58,7 @@ func MakeSettingsWindow(windowWidth, windowHeight int, cfg Settings) *ui.Window
|
|||
func NewSettingsWindow(cfg Settings) *ui.Window {
|
||||
var (
|
||||
Width = 400
|
||||
Height = 400
|
||||
Height = 360
|
||||
)
|
||||
|
||||
window := ui.NewWindow("Settings")
|
||||
|
@ -111,305 +108,98 @@ func (c Settings) makeOptionsTab(tabFrame *ui.TabFrame, Width, Height int) *ui.F
|
|||
|
||||
// Common click handler for all settings,
|
||||
// so we can write the updated info to disk.
|
||||
onClick := func(ed ui.EventData) error {
|
||||
onClick := func() {
|
||||
saveGameSettings()
|
||||
return nil
|
||||
}
|
||||
|
||||
var inputBoxWidth = 120
|
||||
rows := []struct {
|
||||
Header string
|
||||
Text string
|
||||
Boolean *bool
|
||||
Integer *int
|
||||
TextVariable *string
|
||||
Color *render.Color
|
||||
PadY int
|
||||
PadX int
|
||||
name string // for special cases
|
||||
}{
|
||||
{
|
||||
Text: "Notice: all settings are temporary and controls are not editable.",
|
||||
PadY: 2,
|
||||
},
|
||||
{
|
||||
Header: "Game Options",
|
||||
},
|
||||
{
|
||||
Boolean: c.HorizontalToolbars,
|
||||
Text: "Editor: Horizontal instead of vertical toolbars",
|
||||
PadX: 4,
|
||||
name: "toolbars",
|
||||
},
|
||||
{
|
||||
Boolean: c.HideTouchHints,
|
||||
Text: "Hide touchscreen control hints during Play Mode",
|
||||
PadX: 4,
|
||||
name: "toolbars",
|
||||
},
|
||||
{
|
||||
Boolean: c.DisableAutosave,
|
||||
Text: "Disable auto-save in the Editor",
|
||||
PadX: 4,
|
||||
name: "autosave",
|
||||
},
|
||||
{
|
||||
Integer: c.CrosshairSize,
|
||||
Text: "Editor: Crosshair size (0 to disable):",
|
||||
PadX: 4,
|
||||
},
|
||||
{
|
||||
Color: c.CrosshairColor,
|
||||
Text: "Editor: Crosshair color:",
|
||||
PadX: 4,
|
||||
},
|
||||
{
|
||||
Header: "Debug Options (temporary)",
|
||||
},
|
||||
{
|
||||
Boolean: c.DebugOverlay,
|
||||
Text: "Show debug text overlay (F3)",
|
||||
PadX: 4,
|
||||
},
|
||||
{
|
||||
Boolean: c.DebugCollision,
|
||||
Text: "Show collision hitboxes (F4)",
|
||||
PadX: 4,
|
||||
},
|
||||
{
|
||||
Header: "My Custom Content",
|
||||
},
|
||||
{
|
||||
Text: "Levels and doodads you create in-game are placed in your\n" +
|
||||
"Profile Directory, which you can access below:",
|
||||
},
|
||||
// The CrosshairSize is ideally a 0-100 (percent) how big the editor
|
||||
// crosshair is, but options now are only 0% or 100% so it presents
|
||||
// this as a checkbox for now.
|
||||
var crosshairEnabled = *c.CrosshairSize > 0
|
||||
|
||||
form := magicform.Form{
|
||||
Supervisor: c.Supervisor,
|
||||
Engine: c.Engine,
|
||||
Vertical: true,
|
||||
LabelWidth: 150,
|
||||
}
|
||||
for _, row := range rows {
|
||||
row := row
|
||||
frame := ui.NewFrame("Frame")
|
||||
tab.Pack(frame, ui.Pack{
|
||||
Side: ui.N,
|
||||
FillX: true,
|
||||
PadY: row.PadY,
|
||||
})
|
||||
|
||||
// Headers get their own row to themselves.
|
||||
if row.Header != "" {
|
||||
label := ui.NewLabel(ui.Label{
|
||||
Text: row.Header,
|
||||
Font: balance.LabelFont,
|
||||
})
|
||||
frame.Pack(label, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: row.PadX,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// Checkboxes get their own row.
|
||||
if row.Boolean != nil {
|
||||
cb := ui.NewCheckbox(row.Text, row.Boolean, ui.NewLabel(ui.Label{
|
||||
Text: row.Text,
|
||||
Font: balance.UIFont,
|
||||
}))
|
||||
cb.Handle(ui.Click, onClick)
|
||||
cb.Supervise(c.Supervisor)
|
||||
|
||||
// Add warning to the toolbars option if the EditMode is currently active.
|
||||
if row.name == "toolbars" && c.SceneName == "Edit" {
|
||||
ui.NewTooltip(cb, ui.Tooltip{
|
||||
Text: "Note: reload your level after changing this option.\n" +
|
||||
"Playtesting and returning will do.",
|
||||
Edge: ui.Top,
|
||||
})
|
||||
}
|
||||
|
||||
frame.Pack(cb, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: row.PadX,
|
||||
})
|
||||
continue
|
||||
} else {
|
||||
// Reserve indented space where the checkbox would have gone.
|
||||
spacer := ui.NewFrame("Spacer")
|
||||
spacer.Resize(render.NewRect(9, 9)) // TODO: ugly UI hack ;)
|
||||
frame.Pack(spacer, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: row.PadX,
|
||||
})
|
||||
}
|
||||
|
||||
// Any leftover Text gets packed to the left.
|
||||
if row.Text != "" {
|
||||
tf := ui.NewFrame("TextFrame")
|
||||
label := ui.NewLabel(ui.Label{
|
||||
Text: row.Text,
|
||||
Font: balance.UIFont,
|
||||
})
|
||||
tf.Pack(label, ui.Pack{
|
||||
Side: ui.W,
|
||||
})
|
||||
frame.Pack(tf, ui.Pack{
|
||||
Side: ui.W,
|
||||
})
|
||||
}
|
||||
|
||||
// Int variables draw as a button to prompt for new value.
|
||||
// In future: TextVariable works here too.
|
||||
if row.Integer != nil {
|
||||
varButton := ui.NewButton("VarButton", ui.NewLabel(ui.Label{
|
||||
IntVariable: row.Integer,
|
||||
Font: ui.MenuFont,
|
||||
}))
|
||||
varButton.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
shmem.Prompt(row.Text+" ", func(answer string) {
|
||||
if answer == "" {
|
||||
return
|
||||
}
|
||||
|
||||
a, err := strconv.Atoi(answer)
|
||||
if err != nil {
|
||||
shmem.FlashError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if a < 0 {
|
||||
a = 0
|
||||
} else if a > 100 {
|
||||
a = 100
|
||||
}
|
||||
|
||||
*row.Integer = a
|
||||
shmem.Flash("Crosshair size set to %d%% (WIP)", a)
|
||||
|
||||
// call onClick to save change to disk now
|
||||
onClick(ed)
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
varButton.Compute(c.Engine)
|
||||
varButton.Resize(render.Rect{
|
||||
W: inputBoxWidth,
|
||||
H: varButton.Size().H,
|
||||
})
|
||||
|
||||
c.Supervisor.Add(varButton)
|
||||
frame.Pack(varButton, ui.Pack{
|
||||
Side: ui.E,
|
||||
PadX: row.PadX,
|
||||
})
|
||||
}
|
||||
|
||||
// Color picker button.
|
||||
if row.Color != nil {
|
||||
btn := ui.NewButton("ColorBtn", ui.NewFrame(""))
|
||||
style := style.DefaultButton
|
||||
style.Background = *row.Color
|
||||
style.HoverBackground = style.Background.Lighten(20)
|
||||
btn.SetStyle(&style)
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
// Open a ColorPicker widget.
|
||||
picker, err := ui.NewColorPicker(ui.ColorPicker{
|
||||
Title: "Select a color",
|
||||
Supervisor: c.Supervisor,
|
||||
Engine: c.Engine,
|
||||
Color: *row.Color,
|
||||
OnManualInput: func(callback func(render.Color)) {
|
||||
// Prompt the user to enter a hex color using the developer shell.
|
||||
shmem.Prompt("New color in hex notation: ", func(answer string) {
|
||||
if answer != "" {
|
||||
// XXX: pure white renders as invisible, fudge it a bit.
|
||||
if answer == "FFFFFF" {
|
||||
answer = "FFFFFE"
|
||||
}
|
||||
|
||||
color, err := render.HexColor(answer)
|
||||
if err != nil {
|
||||
shmem.Flash("Error with that color code: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
callback(color)
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Couldn't open ColorPicker: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
picker.Then(func(color render.Color) {
|
||||
*row.Color = color
|
||||
style.Background = color
|
||||
style.HoverBackground = style.Background.Lighten(20)
|
||||
|
||||
// call onClick to save change to disk now
|
||||
onClick(ed)
|
||||
})
|
||||
|
||||
picker.Center(shmem.CurrentRenderEngine.WindowSize())
|
||||
picker.Show()
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
btn.Compute(c.Engine)
|
||||
btn.Resize(render.Rect{
|
||||
W: inputBoxWidth,
|
||||
H: 20, // TODO
|
||||
})
|
||||
|
||||
c.Supervisor.Add(btn)
|
||||
frame.Pack(btn, ui.Pack{
|
||||
Side: ui.E,
|
||||
PadX: row.PadX,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Button toolbar.
|
||||
btnFrame := ui.NewFrame("Button Frame")
|
||||
tab.Pack(btnFrame, ui.Pack{
|
||||
Side: ui.N,
|
||||
FillX: true,
|
||||
PadY: 4,
|
||||
})
|
||||
for _, button := range []struct {
|
||||
Label string
|
||||
Fn func()
|
||||
Style *style.Button
|
||||
}{
|
||||
form.Create(tab, []magicform.Field{
|
||||
{
|
||||
Label: "Open profile directory",
|
||||
Fn: func() {
|
||||
path := strings.ReplaceAll(userdir.ProfileDirectory, "\\", "/")
|
||||
if path[0] != '/' {
|
||||
path = "/" + path
|
||||
}
|
||||
native.OpenURL("file://" + path)
|
||||
Label: "Game Options",
|
||||
Font: balance.LabelFont,
|
||||
},
|
||||
{
|
||||
Label: "Hide touchscreen control hints during Play Mode",
|
||||
Font: balance.UIFont,
|
||||
BoolVariable: c.HideTouchHints,
|
||||
},
|
||||
{
|
||||
Label: "Level & Doodad Editor",
|
||||
Font: balance.LabelFont,
|
||||
},
|
||||
{
|
||||
Label: "Horizontal instead of vertical toolbars",
|
||||
Font: balance.UIFont,
|
||||
BoolVariable: c.HorizontalToolbars,
|
||||
Tooltip: ui.Tooltip{
|
||||
Text: "Note: reload your level after changing this option.\n" +
|
||||
"Playtesting and returning will do.",
|
||||
Edge: ui.Top,
|
||||
},
|
||||
Style: &balance.ButtonPrimary,
|
||||
},
|
||||
} {
|
||||
btn := ui.NewButton(button.Label, ui.NewLabel(ui.Label{
|
||||
Text: button.Label,
|
||||
{
|
||||
Label: "Disable auto-save in the Editor",
|
||||
Font: balance.UIFont,
|
||||
BoolVariable: c.DisableAutosave,
|
||||
},
|
||||
{
|
||||
Label: "Draw a crosshair at the mouse cursor.",
|
||||
Font: balance.UIFont,
|
||||
BoolVariable: &crosshairEnabled,
|
||||
OnClick: func() {
|
||||
if crosshairEnabled {
|
||||
*c.CrosshairSize = 100
|
||||
} else {
|
||||
*c.CrosshairSize = 0
|
||||
}
|
||||
onClick()
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: magicform.Color,
|
||||
Label: "Crosshair color:",
|
||||
Font: balance.UIFont,
|
||||
Color: c.CrosshairColor,
|
||||
OnClick: func() {
|
||||
onClick()
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "My Custom Content",
|
||||
Font: balance.LabelFont,
|
||||
},
|
||||
{
|
||||
Label: "Levels and doodads you create in-game are placed in your\n" +
|
||||
"Profile Directory, which you can access below:",
|
||||
Font: balance.UIFont,
|
||||
}))
|
||||
if button.Style != nil {
|
||||
btn.SetStyle(button.Style)
|
||||
}
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
button.Fn()
|
||||
return nil
|
||||
})
|
||||
c.Supervisor.Add(btn)
|
||||
btnFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
Expand: true,
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
Buttons: []magicform.Field{
|
||||
{
|
||||
Label: "Open profile directory",
|
||||
Font: balance.UIFont,
|
||||
ButtonStyle: &balance.ButtonPrimary,
|
||||
OnClick: func() {
|
||||
path := strings.ReplaceAll(userdir.ProfileDirectory, "\\", "/")
|
||||
if path[0] != '/' {
|
||||
path = "/" + path
|
||||
}
|
||||
native.OpenURL("file://" + path)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return tab
|
||||
}
|
||||
|
@ -575,7 +365,7 @@ func (c Settings) makeControlsTab(tabFrame *ui.TabFrame, Width, Height int) *ui.
|
|||
frame.Pack(curFrame, ui.Pack{
|
||||
Side: ui.N,
|
||||
FillX: true,
|
||||
PadY: 2,
|
||||
PadY: 1,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -743,14 +533,13 @@ func (c Settings) makeControllerTab(tabFrame *ui.TabFrame, Width, Height int) *u
|
|||
}
|
||||
form.Create(tab, []magicform.Field{
|
||||
{
|
||||
Label: "About",
|
||||
Label: "Play with an Xbox or Nintendo controller!",
|
||||
Font: balance.LabelFont,
|
||||
},
|
||||
{
|
||||
Label: "Play Sketchy Maze with an Xbox or Nintendo controller!\n\n" +
|
||||
"Full customization options aren't here yet, but you can\n" +
|
||||
"choose between the 'X Style' or 'N Style' profile below.\n" +
|
||||
"'N Style' will swap the A/B and X/Y buttons.",
|
||||
Label: "If you have a Nintendo-style controller (your A button is on\n" +
|
||||
"the right and B button on bottom), pick 'N Style' to reverse\n" +
|
||||
"the A/B and X/Y buttons.",
|
||||
Font: balance.UIFont,
|
||||
},
|
||||
{
|
||||
|
@ -776,7 +565,7 @@ func (c Settings) makeControllerTab(tabFrame *ui.TabFrame, Width, Height int) *u
|
|||
},
|
||||
},
|
||||
{
|
||||
Label: "\nThe gamepad controls vary between two modes:",
|
||||
Label: "The gamepad controls vary between two modes:",
|
||||
Font: balance.UIFont,
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user