func MakeMainBar(game *Game) (*MainBar, error) { var mb MainBar datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "main_bar.json"), "json", &mb.layout) if err != nil { return nil, err } mb.all_buttons = []*Button{ &mb.layout.EndTurn, &mb.layout.UnitLeft, &mb.layout.UnitRight, &mb.layout.ActionLeft, &mb.layout.ActionRight, } mb.no_actions_buttons = []*Button{ &mb.layout.EndTurn, &mb.layout.UnitLeft, &mb.layout.UnitRight, } mb.layout.EndTurn.f = buttonFuncEndTurn mb.layout.UnitRight.f = buttonFuncUnitRight mb.layout.UnitRight.key = gin.Tab mb.layout.UnitLeft.f = buttonFuncUnitLeft mb.layout.UnitLeft.key = gin.ShiftTab mb.layout.ActionLeft.f = buttonFuncActionLeft mb.layout.ActionRight.f = buttonFuncActionRight mb.game = game return &mb, nil }
func InsertCreditsMenu(ui gui.WidgetParent) error { var cm CreditsMenu datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "start", "credits", "layout.json"), "json", &cm.layout) if err != nil { return err } cm.buttons = []ButtonLike{ &cm.layout.Back, &cm.layout.Up, &cm.layout.Down, } cm.layout.Back.f = func(interface{}) { ui.RemoveChild(&cm) InsertStartMenu(ui) } d := base.GetDictionary(cm.layout.Credits.Size) cm.layout.Credits.Scroll.Height = len(cm.layout.Credits.Lines) * int(d.MaxHeight()) cm.layout.Down.valid_func = func() bool { return cm.layout.Credits.Scroll.Height > cm.layout.Credits.Scroll.Dy } cm.layout.Up.valid_func = cm.layout.Down.valid_func cm.layout.Down.f = func(interface{}) { cm.layout.Credits.Scroll.Down() } cm.layout.Up.f = func(interface{}) { cm.layout.Credits.Scroll.Up() } cm.ui = ui ui.AddChild(&cm) return nil }
func makeChooserFromOptionBasicsFile(path string) (*Chooser, <-chan []string, error) { var bops []OptionBasic err := base.LoadAndProcessObject(path, "json", &bops) if err != nil { return nil, nil, err } var opts []Option algorithm.Map2(bops, &opts, func(ob OptionBasic) Option { return &ob }) return MakeChooser(opts) }
func MakeHouseFromPath(path string) (*HouseDef, error) { var house HouseDef err := base.LoadAndProcessObject(path, "json", &house) if err != nil { return nil, err } house.Normalize() house.setDoorsOpened(false) return &house, nil }
func MakeChooser(opts []Option) (*Chooser, <-chan []string, error) { var ch Chooser datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "chooser", "layout.json"), "json", &ch.layout) if err != nil { return nil, nil, err } ch.options = opts ch.buttons = []*Button{ &ch.layout.Up, &ch.layout.Down, &ch.layout.Back, &ch.layout.Next, } ch.non_scroll_buttons = []*Button{ &ch.layout.Back, &ch.layout.Next, } ch.layout.Up.f = func(interface{}) { ch.layout.Options.Up() } ch.layout.Down.f = func(interface{}) { ch.layout.Options.Down() } done := make(chan []string, 1) ch.selected = make(map[int]bool) ch.layout.Back.f = func(interface{}) { done <- nil close(done) } ch.layout.Next.f = func(interface{}) { var res []string for i := range ch.options { if ch.selected[i] { res = append(res, ch.options[i].String()) } } done <- res close(done) } ch.layout.Next.valid_func = func() bool { return ch.selector(-1, ch.selected, false) } ch.min, ch.max = 1, 1 if ch.min == 1 && ch.max == 1 { ch.selector = SelectExactlyOne } else { ch.selector = SelectInRange(ch.min, ch.max) } ch.info_region = gui.Region{ gui.Point{ch.layout.Info.X, ch.layout.Info.Y}, gui.Dims{ch.layout.Info.Dx, ch.layout.Info.Dy}, } return &ch, done, nil }
func (rep *RoomEditorPanel) Load(path string) error { var room roomDef err := base.LoadAndProcessObject(path, "json", &room) if err == nil { rep.room = room for _, tab := range rep.widgets { tab.Reload() } } return err }
func InsertStartMenu(ui gui.WidgetParent) error { var sm StartMenu datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "start", "layout.json"), "json", &sm.layout) if err != nil { return err } sm.buttons = []ButtonLike{ &sm.layout.Menu.Credits, &sm.layout.Menu.Versus, &sm.layout.Menu.Online, &sm.layout.Menu.Settings, } sm.layout.Menu.Credits.f = func(interface{}) { ui.RemoveChild(&sm) err := InsertCreditsMenu(ui) if err != nil { base.Error().Printf("Unable to make Credits Menu: %v", err) return } } sm.layout.Menu.Versus.f = func(interface{}) { ui.RemoveChild(&sm) err := InsertMapChooser( ui, func(name string) { ui.AddChild(MakeGamePanel(name, nil, nil, "")) }, InsertStartMenu, ) if err != nil { base.Error().Printf("Unable to make Map Chooser: %v", err) return } } sm.layout.Menu.Settings.f = func(interface{}) {} sm.layout.Menu.Online.f = func(interface{}) { ui.RemoveChild(&sm) err := InsertOnlineMenu(ui) if err != nil { base.Error().Printf("Unable to make Online Menu: %v", err) return } } ui.AddChild(&sm) return nil }
func MakeSystemMenu(gp *GamePanel, player *Player) (gui.Widget, error) { var sm SystemMenu datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "system", "layout.json"), "json", &sm.layout) if err != nil { return nil, err } sm.layout.Main.f = func(interface{}) {} sm.buttons = []ButtonLike{ &sm.layout.Sub.Return, &sm.layout.Sub.Save, } sm.layout.Sub.Return.f = func(_ui interface{}) { ui := _ui.(*gui.Gui) gp.game.Ents = nil gp.game.Think(1) // This should clean things up ui.DropFocus() Restart() } sm.layout.Sub.Save.Entry.text = player.Name sm.layout.Sub.Save.Button.f = func(interface{}) { UpdatePlayer(player, gp.script.L) str, err := base.ToGobToBase64(gp.game) if err != nil { base.Error().Printf("Error gobbing game state: %v", err) return } player.Game_state = str player.Name = sm.layout.Sub.Save.Text() player.No_init = true base.Log().Printf("Saving player: %v", player) err = SavePlayer(player) if err != nil { base.Warn().Printf("Unable to save player: %v", err) return } sm.saved_time = time.Now() sm.saved_alpha = 1.0 } return &sm, nil }
func MakeRosterChooser(options []Option, selector Selector, on_complete func(map[int]bool), on_undo func()) *RosterChooser { var rc RosterChooser rc.options = options err := base.LoadAndProcessObject(filepath.Join(base.GetDataDir(), "ui", "widgets", "roster_chooser.json"), "json", &rc.layout) if err != nil { base.Error().Printf("Failed to create RosterChooser: %v", err) return nil } rc.Request_dims = gui.Dims{ rc.layout.Down.Data().Dx() + rc.layout.Option.Dx, rc.layout.Num_options*rc.layout.Option.Dy + 2*int(base.GetDictionary(15).MaxHeight()), } rc.selected = make(map[int]bool) rc.selector = selector rc.on_complete = on_complete rc.on_undo = on_undo rc.render.options = make([]gui.Region, len(rc.options)) return &rc }
func MakeUiSelectMap(gp *GamePanel) (gui.Widget, <-chan string, error) { var ui UiSelectMap datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "select_map", "config.json"), "json", &ui.layout) if err != nil { return nil, nil, err } ui.region.Dx = 1024 ui.region.Dy = 768 var options []hui.Option // TODO: may want to reload the registry on this one? If we want to pik up // new changes to files that is. for _, name := range base.GetAllNamesInRegistry("houses") { var mo MapOption mo.house_def = house.MakeHouseFromName(name) mo.layout = &ui.layout options = append(options, &mo) } out := make(chan string, 2) chooser := hui.MakeRosterChooser(options, hui.SelectExactlyOne, func(m map[int]bool) { var index int base.Log().Printf("On complete: %v", m) for index = range m { out <- options[index].(*MapOption).house_def.Name base.Log().Printf("Sent '%s'", options[index].(*MapOption).house_def.Name) break } base.Log().Printf("Closing") close(out) }, nil) ui.chooser = chooser return &ui, out, nil }
func InsertMapChooser(ui gui.WidgetParent, chosen func(string), resert func(ui gui.WidgetParent) error) error { var bops []OptionBasic datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "start", "versus", "map_select.json"), "json", &bops) if err != nil { base.Error().Printf("Unable to insert MapChooser: %v", err) return err } var opts []Option algorithm.Map2(bops, &opts, func(ob OptionBasic) Option { return &ob }) for _, opt := range opts { base.Log().Printf(opt.String()) } var ch Chooser err = base.LoadAndProcessObject(filepath.Join(datadir, "ui", "chooser", "layout.json"), "json", &ch.layout) if err != nil { base.Error().Printf("Unable to insert MapChooser: %v", err) return err } ch.options = opts ch.buttons = []*Button{ &ch.layout.Up, &ch.layout.Down, &ch.layout.Back, &ch.layout.Next, } ch.non_scroll_buttons = []*Button{ &ch.layout.Back, &ch.layout.Next, } ch.layout.Up.f = func(interface{}) { ch.layout.Options.Up() } ch.layout.Down.f = func(interface{}) { ch.layout.Options.Down() } ch.selected = make(map[int]bool) ch.layout.Back.f = func(interface{}) { ui.RemoveChild(&ch) err := resert(ui) if err != nil { base.Error().Printf("Unable to make Start Menu: %v", err) return } } ch.layout.Next.f = func(interface{}) { for i := range ch.options { if ch.selected[i] { ui.RemoveChild(&ch) chosen(ch.options[i].String()) } } } ch.layout.Next.valid_func = func() bool { return ch.selector(-1, ch.selected, false) } ch.min, ch.max = 1, 1 if ch.min == 1 && ch.max == 1 { ch.selector = SelectExactlyOne } else { ch.selector = SelectInRange(ch.min, ch.max) } ch.info_region = gui.Region{ gui.Point{ch.layout.Info.X, ch.layout.Info.Y}, gui.Dims{ch.layout.Info.Dx, ch.layout.Info.Dy}, } ui.AddChild(&ch) return nil }
func MakeDialogBox(source string, args map[string]string) (*MediumDialogBox, <-chan string, error) { var mdb MediumDialogBox datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, source), "json", &mdb.data) if err != nil { return nil, nil, err } err = base.LoadAndProcessObject(filepath.Join(datadir, "ui", "dialog", fmt.Sprintf("%s.json", mdb.data.Size)), "json", &mdb.layout) if err != nil { return nil, nil, err } if _, ok := mdb.data.Pages["Start"]; !ok { return nil, nil, errors.New("Section 'Start' was not specified.") } // Make sure that all of the pages specified by "Next"s are available // in the map for _, page := range mdb.data.Pages { if page.Next != "" { return nil, nil, errors.New(fmt.Sprintf("Specified 'Next': '%s' on a page, but must be in a section on the page.", page.Next)) } for _, section := range page.Sections { if section.Next == "" { continue } if _, ok := mdb.data.Pages[section.Next]; !ok { return nil, nil, errors.New(fmt.Sprintf("Section '%s' specified but doesn't exist.", section.Next)) } } if _, ok := mdb.layout.Formats[page.Format]; !ok { return nil, nil, errors.New(fmt.Sprintf("Unknown dialog box format '%s'.", page.Format)) } if len(page.Sections) != len(mdb.layout.Formats[page.Format].Sections) { return nil, nil, errors.New(fmt.Sprintf("Format '%s' requires exactly %d sections.", page.Format, len(mdb.layout.Formats[page.Format].Sections))) } } mdb.data.cur_page = "Start" mdb.format = mdb.layout.Formats[mdb.data.Pages[mdb.data.cur_page].Format] // return nil, nil, errors.New(fmt.Sprintf("Unknown format string: '%s'.", format)) mdb.buttons = []*Button{ &mdb.layout.Next, &mdb.layout.Prev, } mdb.result = make(chan string, 1) mdb.layout.Next.valid_func = func() bool { sections := mdb.data.Pages[mdb.data.cur_page].Sections return len(sections) == 1 } mdb.layout.Next.f = func(_data interface{}) { sections := mdb.data.Pages[mdb.data.cur_page].Sections if len(sections) == 1 { if sections[0].Next == "" { if !mdb.done { close(mdb.result) mdb.done = true } } else { mdb.data.prev = append(mdb.data.prev, mdb.data.cur_page) mdb.data.cur_page = sections[0].Next mdb.format = mdb.layout.Formats[mdb.data.Pages[mdb.data.cur_page].Format] } } } mdb.layout.Prev.valid_func = func() bool { return len(mdb.data.prev) > 0 } mdb.layout.Prev.f = func(_data interface{}) { if len(mdb.data.prev) > 0 { mdb.data.cur_page = mdb.data.prev[len(mdb.data.prev)-1] mdb.data.prev = mdb.data.prev[0 : len(mdb.data.prev)-1] mdb.format = mdb.layout.Formats[mdb.data.Pages[mdb.data.cur_page].Format] } } mdb.data.process(args) return &mdb, mdb.result, nil }
func InsertOnlineMenu(ui gui.WidgetParent) error { var sm OnlineMenu datadir := base.GetDataDir() err := base.LoadAndProcessObject(filepath.Join(datadir, "ui", "start", "online", "layout.json"), "json", &sm.layout) if err != nil { return err } sm.buttons = []ButtonLike{ &sm.layout.Back, &sm.layout.Unstarted.Up, &sm.layout.Unstarted.Down, &sm.layout.Active.Up, &sm.layout.Active.Down, &sm.layout.User, &sm.layout.NewGame, } sm.control.in = make(chan struct{}) sm.control.out = make(chan struct{}) sm.layout.Back.f = func(interface{}) { ui.RemoveChild(&sm) InsertStartMenu(ui) } sm.ui = ui fmt.Sscanf(base.GetStoreVal("netid"), "%d", &net_id) if net_id == 0 { net_id = mrgnet.NetId(mrgnet.RandomId()) base.SetStoreVal("netid", fmt.Sprintf("%d", net_id)) } in_newgame := false sm.layout.NewGame.f = func(interface{}) { if in_newgame { return } in_newgame = true go func() { var req mrgnet.NewGameRequest req.Id = net_id var resp mrgnet.NewGameResponse done := make(chan bool, 1) go func() { mrgnet.DoAction("new", req, &resp) done <- true }() select { case <-done: case <-time.After(5 * time.Second): resp.Err = "Couldn't connect to server." } <-sm.control.in defer func() { in_newgame = false sm.control.out <- struct{}{} }() if resp.Err != "" { sm.layout.Error.err = resp.Err base.Error().Printf("Couldn't make new game: %v", resp.Err) return } ui.RemoveChild(&sm) err := InsertMapChooser( ui, func(name string) { ui.AddChild(MakeGamePanel(name, nil, nil, resp.Game_key)) }, InsertOnlineMenu, ) if err != nil { base.Error().Printf("Error making Map Chooser: %v", err) } }() } for _, _glb := range []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted} { glb := _glb glb.Up.f = func(interface{}) { glb.Scroll.Up() } glb.Up.valid_func = func() bool { return glb.Scroll.Height > glb.Scroll.Dy } glb.Down.f = func(interface{}) { glb.Scroll.Down() } glb.Down.valid_func = func() bool { return glb.Scroll.Height > glb.Scroll.Dy } glb.update = make(chan mrgnet.ListGamesResponse) } go func() { var resp mrgnet.ListGamesResponse mrgnet.DoAction("list", mrgnet.ListGamesRequest{Id: net_id, Unstarted: true}, &resp) sm.layout.Unstarted.update <- resp }() go func() { var resp mrgnet.ListGamesResponse mrgnet.DoAction("list", mrgnet.ListGamesRequest{Id: net_id, Unstarted: false}, &resp) sm.layout.Active.update <- resp }() sm.layout.User.Button.f = func(interface{}) { var req mrgnet.UpdateUserRequest req.Name = sm.layout.User.Entry.text req.Id = net_id var resp mrgnet.UpdateUserResponse go func() { mrgnet.DoAction("user", req, &resp) <-sm.control.in sm.layout.User.SetText(resp.Name) sm.update_alpha = 1.0 sm.update_time = time.Now() sm.control.out <- struct{}{} }() } go func() { var resp mrgnet.UpdateUserResponse mrgnet.DoAction("user", mrgnet.UpdateUserRequest{Id: net_id}, &resp) <-sm.control.in sm.layout.User.SetText(resp.Name) sm.update_alpha = 1.0 sm.update_time = time.Now() sm.control.out <- struct{}{} }() ui.AddChild(&sm) return nil }
func MakeEntityPlacer(game *Game, roster_names []string, roster_costs []int, min, max int, pattern string) (*EntityPlacer, <-chan []*Entity, error) { var ep EntityPlacer err := base.LoadAndProcessObject(filepath.Join(base.GetDataDir(), "ui", "entity_placer", "config.json"), "json", &ep.layout) if err != nil { return nil, nil, err } if len(roster_names) != len(roster_costs) { return nil, nil, errors.New("Must have as many names as costs.") } if len(roster_names) <= 0 || len(roster_names) > ep.layout.Roster.Max_options { return nil, nil, errors.New(fmt.Sprintf("Can't have more than %d ents in a roster.", ep.layout.Roster.Max_options)) } ep.layout.Undo.valid_func = func() bool { return len(ep.ents) > 0 } ep.layout.Undo.f = func(interface{}) { ent := ep.ents[len(ep.ents)-1] ep.points += ep.roster[ent.Name] ep.ents = ep.ents[0 : len(ep.ents)-1] algorithm.Choose(&game.Ents, func(e *Entity) bool { return e != ent }) game.viewer.RemoveDrawable(ent) } ep.layout.Done.valid_func = func() bool { return ep.points >= 0 && min <= (max-ep.points) } done := make(chan []*Entity) ep.layout.Done.f = func(interface{}) { done <- ep.ents close(done) house.PopSpawnRegexp() game.viewer.RemoveDrawable(game.new_ent) game.new_ent = nil } ep.roster_names = roster_names ep.roster = make(map[string]int) for i, name := range ep.roster_names { ep.roster[name] = roster_costs[i] } ep.game = game ep.show_points = !(min == 1 && max == 1) ep.points = max ep.pattern = pattern house.PushSpawnRegexp(ep.pattern) x := ep.layout.Roster.X for _, name := range ep.roster_names { var b Button b.X = x x += (ep.layout.Roster.X2 - ep.layout.Roster.X) / (ep.layout.Roster.Max_options - 1) b.Y = ep.layout.Roster.Y ent := Entity{Defname: name} base.GetObject("entities", &ent) b.Texture = ent.Still cost := ep.roster[name] b.valid_func = func() bool { return ep.points >= cost } b.f = func(interface{}) { ep.game.viewer.RemoveDrawable(ep.game.new_ent) ep.game.new_ent = MakeEntity(ent.Name, ep.game) ep.game.viewer.AddDrawable(ep.game.new_ent) } ep.ent_buttons = append(ep.ent_buttons, &b) } ep.buttons = []*Button{ &ep.layout.Undo, &ep.layout.Done, } for _, b := range ep.ent_buttons { ep.buttons = append(ep.buttons, b) } return &ep, done, nil }