224 lines
6.0 KiB
Go
224 lines
6.0 KiB
Go
package shell
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"aego/core/ids"
|
|
"aego/core/mathx"
|
|
"aego/editor/core/command"
|
|
"aego/editor/core/play"
|
|
"aego/editor/core/templates"
|
|
"aego/editor/core/workspace"
|
|
"aego/ui/widgets"
|
|
)
|
|
|
|
func (a *App) menuCategories() []string {
|
|
reg := a.ctx.Commands
|
|
base := []string{"File", "Edit", "Create", "Scene", "Play", "Assets", "Window"}
|
|
known := map[string]bool{}
|
|
var out []string
|
|
for _, c := range base {
|
|
known[c] = true
|
|
if c == "Create" || len(reg.Category(c)) > 0 {
|
|
out = append(out, c)
|
|
}
|
|
}
|
|
for _, c := range reg.Categories() {
|
|
if !known[c] {
|
|
out = append(out, c)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (a *App) commandItems(cat string) {
|
|
ui := a.ui
|
|
reg := a.ctx.Commands
|
|
last := -1
|
|
for _, d := range reg.Category(cat) {
|
|
if last >= 0 && d.Order/100 != last/100 {
|
|
widgets.Separator(ui)
|
|
}
|
|
last = d.Order
|
|
label := d.Name
|
|
if d.Label != nil {
|
|
label = d.Label()
|
|
}
|
|
it := widgets.Item{
|
|
Label: label,
|
|
Shortcut: d.Shortcut.String(),
|
|
Icon: d.Icon,
|
|
Tip: d.Tip,
|
|
Enabled: reg.Enabled(d.ID),
|
|
Checked: d.Checked != nil && d.Checked(),
|
|
}
|
|
if widgets.Entry(ui, it) {
|
|
reg.Run(d.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (a *App) sceneDocs() {
|
|
ui := a.ui
|
|
docs := a.ctx.Docs.Docs()
|
|
if len(docs) == 0 {
|
|
return
|
|
}
|
|
widgets.Separator(ui)
|
|
active := a.ctx.Docs.Edit()
|
|
for _, d := range docs {
|
|
name := d.Path
|
|
if d.Dirty() {
|
|
name += " *"
|
|
}
|
|
if widgets.MenuItem(ui, name, "", true, active != nil && d.ID == active.ID) {
|
|
a.ctx.Docs.SetActive(d.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (a *App) drawMenuBar(r mathx.Rect) {
|
|
ui := a.ui
|
|
ctx := a.ctx
|
|
mb := widgets.BeginMenuBar(ui, r)
|
|
for _, cat := range a.menuCategories() {
|
|
if !mb.Menu(cat, 280) {
|
|
continue
|
|
}
|
|
switch cat {
|
|
case "Create":
|
|
parent := ids.NodeID{}
|
|
if it, ok := ctx.Selection.Active(); ok && ctx.Doc() != nil && it.Doc == ctx.Doc().ID {
|
|
parent = it.Node
|
|
}
|
|
templates.Menu(ctx, a.templates, parent, templates.Place{}, nil)
|
|
case "Scene":
|
|
a.commandItems(cat)
|
|
a.sceneDocs()
|
|
default:
|
|
a.commandItems(cat)
|
|
}
|
|
mb.EndMenu()
|
|
}
|
|
if !a.opt.Supervised || a.buildState == widgets.DotOK {
|
|
return
|
|
}
|
|
label, tip := "native building", "Native code is being rebuilt"
|
|
if a.buildState == widgets.DotError {
|
|
label = "Native API is stale"
|
|
tip = "The last native build failed; the editor and scripts use the previous native API. Click to see the build output"
|
|
}
|
|
w := ui.TextSize(label).X + 24
|
|
dr := mathx.Rect{X: r.X + r.W - 8 - w, Y: r.Y + 2, W: w, H: r.H - 4}
|
|
if dr.X <= mb.X()+16 {
|
|
return
|
|
}
|
|
did := ui.ID("native")
|
|
if widgets.StatusDot(ui, did, dr, a.buildState, label) && a.buildState == widgets.DotError {
|
|
a.ws.Show(workspace.Console)
|
|
a.consolePanel.Focus("build")
|
|
}
|
|
widgets.Tooltip(ui, did, tip)
|
|
}
|
|
|
|
func (a *App) drawToolbar(r mathx.Rect) {
|
|
ui := a.ui
|
|
th := &ui.Theme
|
|
reg := a.ctx.Commands
|
|
st := a.play.State()
|
|
tb := widgets.BeginToolbar(ui, r)
|
|
saveX := r.X + r.W - tb.ButtonW() - 6
|
|
wsLabel := a.ws.Current().Title + " "
|
|
wsX := saveX - ui.TextSize(wsLabel).X - 22
|
|
bw := tb.ButtonW()
|
|
scale, tick := scaleLabel(a.play.TimeScale())+" ", "+1 tick"
|
|
width := 4*bw + ui.TextSize(scale).X + ui.TextSize(tick).X + 28 + 2*9 + 8
|
|
x := max(r.X+(r.W-width)/2, r.X+6)
|
|
sid := ui.ID("tb.scale")
|
|
if x+width <= wsX-8 {
|
|
if st != play.Stopped {
|
|
glow := th.PlayTint
|
|
glow.A = 0.22
|
|
ui.RoundRect(mathx.Rect{X: x, Y: r.Y + 2, W: width, H: r.H - 4}, th.Radius.Popup, glow)
|
|
tb.Label = th.Text
|
|
}
|
|
tb.Active = th.Accent
|
|
tb.SetX(x + 4)
|
|
a.playRect = mathx.Rect{X: x + 4, Y: r.Y + 3, W: bw - 2, H: r.H - 6}
|
|
blocked := 0
|
|
if st == play.Stopped {
|
|
blocked = a.scriptErrors()
|
|
}
|
|
playTip := "Play (" + reg.Shortcut(command.PlayStart) + "), full screen (" + reg.Shortcut(CommandFullscreenPlay) + ")"
|
|
noSource := st == play.Stopped && a.ctx.Docs.Edit() != nil && !a.canPlay()
|
|
switch {
|
|
case blocked > 0:
|
|
playTip = strconv.Itoa(blocked) + " script package error(s), see Problems"
|
|
case noSource:
|
|
playTip = playPrefabHint
|
|
}
|
|
playTint := th.Accent
|
|
if st == play.Playing {
|
|
playTint = th.Text
|
|
}
|
|
if tb.TintButton(ui.ID("tb.play"), "play.start", playTip, st == play.Playing, blocked == 0 && !noSource, playTint) {
|
|
switch st {
|
|
case play.Stopped:
|
|
reg.Run(command.PlayStart)
|
|
case play.Paused:
|
|
a.play.Pause()
|
|
}
|
|
}
|
|
if tb.Button(ui.ID("tb.pause"), "play.pause", "Pause ("+reg.Shortcut(command.PlayPause)+")", st == play.Paused, st != play.Stopped) {
|
|
a.play.Pause()
|
|
}
|
|
if tb.Button(ui.ID("tb.step"), "play.step", "Step one frame ("+reg.Shortcut(command.PlayStep)+")", false, st == play.Paused) {
|
|
a.play.Step()
|
|
}
|
|
if clicked, _ := tb.TextButton(ui.ID("tb.tick"), tick, "Step one fixed tick ("+reg.Shortcut(command.PlayStepFixed)+"), while paused"); clicked && reg.Enabled(command.PlayStepFixed) {
|
|
reg.Run(command.PlayStepFixed)
|
|
}
|
|
tb.Separator()
|
|
clicked, sr := tb.TextButton(sid, scale, "Time scale")
|
|
caret := th.TextDim
|
|
if tb.Label.A > 0 {
|
|
caret = tb.Label
|
|
}
|
|
widgets.Chevron(ui, mathx.Rect{X: sr.X + sr.W - 21, Y: float32(int(sr.Y + (sr.H-19)/2 + 1)), W: 19, H: 19}, true, caret)
|
|
if clicked {
|
|
if ui.PopupOpen(sid) {
|
|
ui.ClosePopup(sid)
|
|
} else {
|
|
ui.CloseAllPopups()
|
|
ui.OpenPopup(sid, mathx.Vec2{X: sr.X, Y: sr.Y + sr.H})
|
|
}
|
|
}
|
|
tb.Separator()
|
|
tb.Active = th.Error
|
|
if tb.TintButton(ui.ID("tb.stop"), "play.stop", "Stop", st != play.Stopped, st != play.Stopped, th.Text) {
|
|
a.stopPlay()
|
|
}
|
|
tb.Active, tb.Label = mathx.Color{}, mathx.Color{}
|
|
}
|
|
wid := ui.ID("tb.workspace")
|
|
if wsX > r.X+6 {
|
|
tb.SetX(wsX)
|
|
clicked, wr := tb.TextButton(wid, wsLabel, "Workspace ("+reg.Shortcut(WorkspaceCommand(0))+"…4)")
|
|
widgets.Chevron(ui, mathx.Rect{X: wr.X + wr.W - 21, Y: float32(int(wr.Y + (wr.H-19)/2 + 1)), W: 19, H: 19}, true, th.TextDim)
|
|
if clicked {
|
|
if ui.PopupOpen(wid) {
|
|
ui.ClosePopup(wid)
|
|
} else {
|
|
ui.CloseAllPopups()
|
|
ui.OpenPopup(wid, mathx.Vec2{X: wr.X, Y: wr.Y + wr.H})
|
|
}
|
|
}
|
|
}
|
|
tb.SetX(saveX)
|
|
if tb.Button(ui.ID("tb.save"), "file.save", "Save ("+reg.Shortcut(command.FileSave)+")", false, reg.Enabled(command.FileSave)) {
|
|
reg.Run(command.FileSave)
|
|
}
|
|
a.scalePopup(sid)
|
|
a.workspacePopup(wid)
|
|
}
|