func (b *Button) RenderAt(x, y int) { gl.Color4ub(255, 255, 255, byte(b.shade*255)) if b.Texture.Path != "" { b.Texture.Data().RenderNatural(b.X+x, b.Y+y) b.bounds.x = b.X + x b.bounds.y = b.Y + y b.bounds.dx = b.Texture.Data().Dx() b.bounds.dy = b.Texture.Data().Dy() } else { d := base.GetDictionary(b.Text.Size) b.bounds.x = b.X + x b.bounds.y = b.Y + y b.bounds.dx = int(d.StringWidth(b.Text.String)) b.bounds.dy = int(d.MaxHeight()) var just gui.Justification switch b.Text.Justification { case "center": just = gui.Center b.bounds.x -= b.bounds.dx / 2 case "left": just = gui.Left case "right": just = gui.Right b.bounds.x -= b.bounds.dx default: just = gui.Center b.bounds.x -= b.bounds.dx / 2 b.Text.Justification = "center" } d.RenderString(b.Text.String, float64(b.X+x), float64(b.Y+y), 0, d.MaxHeight(), just) } }
// Returns true iff the position specified is a valid position to click in the // text area. Also sets everything up so that if te.Entry.entering can be set // to true to begin editing at that position. func (te *TextEntry) setCursor(mx, my int) bool { if !pointInsideRect(mx, my, te.Entry.bounds.x, te.Entry.bounds.y, te.Entry.bounds.dx, te.Entry.bounds.dy) { te.Entry.ghost.offset = -1 return false } d := base.GetDictionary(te.Button.Text.Size) last_dx := 0 te.Entry.ghost.index = -1 for i := range te.Entry.text { w := int(d.StringWidth(te.Entry.text[0 : i+1])) avg := (last_dx + w) / 2 if pointInsideRect(mx, my, te.Entry.bounds.x, te.Entry.bounds.y, avg, te.Entry.bounds.dy) { te.Entry.ghost.offset = last_dx te.Entry.ghost.index = i break } last_dx = w } if te.Entry.ghost.index < 0 { te.Entry.ghost.offset = int(d.StringWidth(te.Entry.text)) te.Entry.ghost.index = len(te.Entry.text) } return true }
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 (ob *OptionBasic) DrawInfo(x, y, dx, dy int) { gl.Color4ub(255, 255, 255, 255) tx := x + (dx-ob.Large.Data().Dx())/2 ty := y + dy - ob.Large.Data().Dy() ob.Large.Data().RenderNatural(tx, ty) d := base.GetDictionary(ob.Size) d.RenderParagraph(ob.Text, float64(x), float64(y+dy-ob.Large.Data().Dy())-d.MaxHeight(), 0, float64(dx), d.MaxHeight(), gui.Left, gui.Top) }
func (ep *EntityPlacer) Draw(region gui.Region) { ep.region = region gl.Color4ub(255, 255, 255, 255) ep.layout.Texture.Data().RenderNatural(region.X, region.Y) for _, button := range ep.buttons { button.RenderAt(ep.region.X, ep.region.Y) } d := base.GetDictionary(ep.layout.Roster.Points.Size) x_off := ep.layout.Roster.Points.X_off y_off := ep.layout.Roster.Points.Y_off for i, button := range ep.ent_buttons { cost := ep.roster[ep.roster_names[i]] x := float64(button.X + x_off) y := float64(button.Y + y_off) d.RenderString(fmt.Sprintf("%d", cost), x, y, 0, d.MaxHeight(), gui.Right) } gl.Color4ub(255, 255, 255, 255) var ent *Entity if !pointInsideRect(ep.mx, ep.my, region.X, region.Y, region.Dx, region.Dy) { ent = ep.game.new_ent } if ep.hovered != nil { ent = ep.hovered } if ent != nil { ent.Still.Data().RenderNatural(ep.layout.Face.X, ep.layout.Face.Y) ep.layout.Name.RenderString(ent.Name) ep.layout.Ap.RenderString(fmt.Sprintf("Ap:%d", ent.Stats.ApCur())) ep.layout.Hp.RenderString(fmt.Sprintf("Hp:%d", ent.Stats.HpCur())) ep.layout.Corpus.RenderString(fmt.Sprintf("Corpus:%d", ent.Stats.Corpus())) ep.layout.Ego.RenderString(fmt.Sprintf("Ego:%d", ent.Stats.Ego())) } if ep.show_points { d := base.GetDictionary(ep.layout.Points_remaining.Size) x := float64(ep.layout.Points_remaining.X) y := float64(ep.layout.Points_remaining.Y) d.RenderString(ep.layout.Points_remaining.String, x, y, 0, d.MaxHeight(), gui.Left) w := d.StringWidth(ep.layout.Points_remaining.String) d.RenderString(fmt.Sprintf("%d", ep.points), x+w, y, 0, d.MaxHeight(), gui.Right) } }
func (te *TextEntry) Respond(group gui.EventGroup, data interface{}) bool { if te.Button.Respond(group, data) { return true } if !te.Entry.entering { return false } for _, event := range group.Events { if event.Type == gin.Press { id := event.Key.Id() if id <= 255 && valid_keys[byte(id)] { b := byte(id) if gin.In().GetKey(gin.EitherShift).CurPressAmt() > 0 { b = shift_keys[b] } t := te.Entry.text index := te.Entry.cursor.index t = t[0:index] + string([]byte{b}) + t[index:] te.Entry.text = t te.Entry.cursor.index++ } else if event.Key.Id() == gin.DeleteOrBackspace { if te.Entry.cursor.index > 0 { index := te.Entry.cursor.index t := te.Entry.text te.Entry.text = t[0:index-1] + t[index:] te.Entry.cursor.index-- } } else if event.Key.Id() == gin.Left { if te.Entry.cursor.index > 0 { te.Entry.cursor.index-- } } else if event.Key.Id() == gin.Right { if te.Entry.cursor.index < len(te.Entry.text) { te.Entry.cursor.index++ } } else if event.Key.Id() == gin.Return { te.Entry.entering = false if te.Button.f != nil { te.Button.f(nil) } } else if event.Key.Id() == gin.Escape { te.Entry.entering = false te.Entry.text = te.Entry.prev te.Entry.prev = "" te.Entry.cursor.index = 0 } d := base.GetDictionary(te.Button.Text.Size) te.Entry.cursor.offset = int(d.StringWidth(te.Entry.text[0:te.Entry.cursor.index])) } } return false }
func (te *TextEntry) RenderAt(x, y int) { te.Button.RenderAt(x, y) d := base.GetDictionary(te.Button.Text.Size) x += te.Entry.X y += te.Button.Y x2 := x + te.Entry.Dx y2 := y + int(d.MaxHeight()) te.Entry.bounds.x = x te.Entry.bounds.y = y te.Entry.bounds.dx = x2 - x te.Entry.bounds.dy = y2 - y gl.Disable(gl.TEXTURE_2D) if te.Entry.entering { gl.Color4ub(255, 255, 255, 255) } else { gl.Color4ub(255, 255, 255, 128) } gl.Begin(gl.QUADS) gl.Vertex2i(x-3, y-3) gl.Vertex2i(x-3, y2+3) gl.Vertex2i(x2+3, y2+3) gl.Vertex2i(x2+3, y-3) gl.End() gl.Color4ub(0, 0, 0, 255) gl.Begin(gl.QUADS) gl.Vertex2i(x, y) gl.Vertex2i(x, y2) gl.Vertex2i(x2, y2) gl.Vertex2i(x2, y) gl.End() gl.Color4ub(255, 255, 255, 255) d.RenderString(te.Entry.text, float64(x), float64(y), 0, d.MaxHeight(), gui.Left) if te.Entry.ghost.offset >= 0 { gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 100, 100, 127) gl.Begin(gl.LINES) gl.Vertex2i(te.Entry.bounds.x+te.Entry.ghost.offset, te.Entry.bounds.y) gl.Vertex2i(te.Entry.bounds.x+te.Entry.ghost.offset, te.Entry.bounds.y+te.Entry.bounds.dy) gl.End() } if te.Entry.entering { gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 100, 100, 255) gl.Begin(gl.LINES) gl.Vertex2i(te.Entry.bounds.x+te.Entry.cursor.offset, te.Entry.bounds.y) gl.Vertex2i(te.Entry.bounds.x+te.Entry.cursor.offset, te.Entry.bounds.y+te.Entry.bounds.dy) gl.End() } }
func (mdb *MediumDialogBox) Draw(region gui.Region) { mdb.region = region if mdb.done { return } gl.Enable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) mdb.layout.Background.Data().RenderNatural(region.X, region.Y) for _, button := range mdb.buttons { button.RenderAt(region.X, region.Y) } for i := range mdb.format.Sections { section := mdb.format.Sections[i] data := mdb.data.Pages[mdb.data.cur_page].Sections[i] p := section.Paragraph d := base.GetDictionary(p.Size) var just gui.Justification switch p.Halign { case "left": just = gui.Left case "right": just = gui.Right case "center": just = gui.Center default: base.Error().Printf("Unknown justification '%s'", p.Halign) p.Halign = "left" } var valign gui.Justification switch p.Valign { case "top": valign = gui.Top case "bottom": valign = gui.Bottom case "center": valign = gui.Center default: base.Error().Printf("Unknown justification '%s'", p.Valign) p.Valign = "top" } gl.Color4ub(255, 255, 255, 255) d.RenderParagraph(data.Text, float64(p.X+region.X), float64(p.Y+region.Y)-d.MaxHeight()/2, 0, float64(p.Dx), d.MaxHeight(), just, valign) gl.Color4ub(255, 255, 255, byte(data.shading*255)) tex := data.Image.Data() tex.RenderNatural(region.X+section.X-tex.Dx()/2, region.Y+section.Y-tex.Dy()/2) } }
func (sm *SystemMenu) DrawFocused(region gui.Region) { sm.region = region gl.Color4ub(255, 255, 255, 255) x := region.X + region.Dx/2 - sm.layout.Sub.Background.Data().Dx()/2 y := region.Y + region.Dy/2 - sm.layout.Sub.Background.Data().Dy()/2 sm.layout.Sub.Background.Data().RenderNatural(x, y) for _, button := range sm.buttons { button.RenderAt(x, y) } gl.Color4ub(255, 255, 255, byte(255*sm.saved_alpha)) d := base.GetDictionary(sm.layout.Sub.Save.Button.Text.Size) sx := x + sm.layout.Sub.Save.Entry.X + sm.layout.Sub.Save.Entry.Dx + 10 sy := y + sm.layout.Sub.Save.Button.Y d.RenderString("Game Saved!", float64(sx), float64(sy), 0, d.MaxHeight(), gui.Left) }
func (t *TextArea) RenderString(s string) { var just gui.Justification switch t.Justification { case "center": just = gui.Center case "left": just = gui.Left case "right": just = gui.Right default: base.Warn().Printf("Unknown justification '%s' in main gui bar.", t.Justification) t.Justification = "center" } px := float64(t.X) py := float64(t.Y) d := base.GetDictionary(t.Size) d.RenderString(s, px, py, 0, d.MaxHeight(), just) }
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 (mo *MapOption) Draw(hovered, selected, selectable bool, region gui.Region) { var s gl.Ubyte switch { case selected: s = 255 case hovered && selectable: s = 205 case selectable: s = 127 default: s = 75 } gl.Color4ub(s, s, s, 255) icon := mo.house_def.Icon.Data() if icon.Dx() == 0 { icon = mo.layout.Default_icon.Data() } icon.RenderNatural(region.X, region.Y) gl.Color4ub(0, 0, 0, 255) d := base.GetDictionary(15) d.RenderString(mo.house_def.Name, float64(region.X), float64(region.Y), 0, d.MaxHeight(), gui.Left) }
func (cm *CreditsMenu) Draw(region gui.Region) { cm.region = region gl.Color4ub(255, 255, 255, 255) cm.layout.Background.Data().RenderNatural(region.X, region.Y) title := cm.layout.Title title.Texture.Data().RenderNatural(region.X+title.X, region.Y+title.Y) for _, button := range cm.buttons { button.RenderAt(cm.region.X, cm.region.Y) } d := base.GetDictionary(cm.layout.Credits.Size) sx := cm.layout.Credits.Scroll.X sy := cm.layout.Credits.Scroll.Top() cm.layout.Credits.Scroll.Region().PushClipPlanes() gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) for _, line := range cm.layout.Credits.Lines { sy -= int(d.MaxHeight()) d.RenderString(line, float64(sx), float64(sy), 0, d.MaxHeight(), gui.Left) } cm.layout.Credits.Scroll.Region().PopClipPlanes() }
func (sm *OnlineMenu) Draw(region gui.Region) { sm.region = region gl.Color4ub(255, 255, 255, 255) sm.layout.Background.Data().RenderNatural(region.X, region.Y) title := sm.layout.Title title.Texture.Data().RenderNatural(region.X+title.X, region.Y+title.Y) for _, button := range sm.buttons { button.RenderAt(sm.region.X, sm.region.Y) } d := base.GetDictionary(sm.layout.Text.Size) for _, glb := range []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted} { title_d := base.GetDictionary(glb.Title.Size) title_x := float64(glb.Scroll.X + glb.Scroll.Dx/2) title_y := float64(glb.Scroll.Y + glb.Scroll.Dy) gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) title_d.RenderString(glb.Title.Text, title_x, title_y, 0, title_d.MaxHeight(), gui.Center) sx := glb.Scroll.X sy := glb.Scroll.Top() glb.Scroll.Region().PushClipPlanes() for _, game := range glb.games { sy -= int(d.MaxHeight()) game.join.RenderAt(sx, sy) gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) d.RenderString(game.name, float64(sx+50), float64(sy), 0, d.MaxHeight(), gui.Left) if game.delete != nil { game.delete.RenderAt(sx+50+glb.Scroll.Dx-100, sy) } } glb.Scroll.Region().PopClipPlanes() } gl.Color4ub(255, 255, 255, byte(255*sm.update_alpha)) sx := sm.layout.User.Entry.X + sm.layout.User.Entry.Dx + 10 sy := sm.layout.User.Button.Y d.RenderString("Name Updated", float64(sx), float64(sy), 0, d.MaxHeight(), gui.Left) if sm.hover_game != nil { game := sm.hover_game gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) d := base.GetDictionary(sm.layout.GameStats.Size) x := float64(sm.layout.GameStats.X + sm.layout.GameStats.Dx/2) y := float64(sm.layout.GameStats.Y+sm.layout.GameStats.Dy) - d.MaxHeight() if game.game.Denizens_id == net_id { d.RenderString("You: Denizens", x, y, 0, d.MaxHeight(), gui.Center) } else { d.RenderString("You: Intruders", x, y, 0, d.MaxHeight(), gui.Center) } y -= d.MaxHeight() if game.game.Denizens_id == net_id { var opponent string if game.game.Intruders_name == "" { opponent = "no opponent yet" } else { opponent = fmt.Sprintf("Vs: %s", game.game.Intruders_name) } d.RenderString(opponent, x, y, 0, d.MaxHeight(), gui.Center) } else { d.RenderString(fmt.Sprintf("Vs: %s", game.game.Denizens_name), x, y, 0, d.MaxHeight(), gui.Center) } y -= d.MaxHeight() if (game.game.Denizens_id == net_id) == (len(game.game.Execs)%2 == 0) { d.RenderString("Your move", x, y, 0, d.MaxHeight(), gui.Center) } else { d.RenderString("Their move", x, y, 0, d.MaxHeight(), gui.Center) } } if sm.layout.Error.err != "" { gl.Color4ub(255, 0, 0, 255) l := sm.layout.Error d := base.GetDictionary(l.Size) d.RenderString(fmt.Sprintf("ERROR: %s", l.err), float64(l.X), float64(l.Y), 0, d.MaxHeight(), gui.Left) } }
func (m *MainBar) Draw(region gui.Region) { m.region = region gl.Enable(gl.TEXTURE_2D) m.layout.Background.Data().Bind() gl.Color4d(1, 1, 1, 1) gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(region.X, region.Y) gl.TexCoord2d(0, -1) gl.Vertex2i(region.X, region.Y+region.Dy) gl.TexCoord2d(1, -1) gl.Vertex2i(region.X+region.Dx, region.Y+region.Dy) gl.TexCoord2d(1, 0) gl.Vertex2i(region.X+region.Dx, region.Y) gl.End() buttons := m.no_actions_buttons if m.ent != nil && len(m.ent.Actions) > m.layout.Actions.Count { buttons = m.all_buttons } for _, button := range buttons { button.RenderAt(region.X, region.Y) } ent := m.game.HoveredEnt() if ent == nil { ent = m.ent } if ent != nil && ent.Stats != nil { gl.Color4d(1, 1, 1, 1) ent.Still.Data().Bind() tdx := ent.Still.Data().Dx() tdy := ent.Still.Data().Dy() cx := region.X + m.layout.CenterStillFrame.X cy := region.Y + m.layout.CenterStillFrame.Y gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(cx-tdx/2, cy-tdy/2) gl.TexCoord2d(0, -1) gl.Vertex2i(cx-tdx/2, cy+tdy/2) gl.TexCoord2d(1, -1) gl.Vertex2i(cx+tdx/2, cy+tdy/2) gl.TexCoord2d(1, 0) gl.Vertex2i(cx+tdx/2, cy-tdy/2) gl.End() m.layout.Name.RenderString(ent.Name) m.layout.Ap.RenderString(fmt.Sprintf("Ap:%d", ent.Stats.ApCur())) m.layout.Hp.RenderString(fmt.Sprintf("Hp:%d", ent.Stats.HpCur())) m.layout.Corpus.RenderString(fmt.Sprintf("Corpus:%d", ent.Stats.Corpus())) m.layout.Ego.RenderString(fmt.Sprintf("Ego:%d", ent.Stats.Ego())) gl.Color4d(1, 1, 1, 1) m.layout.Divider.Data().Bind() tdx = m.layout.Divider.Data().Dx() tdy = m.layout.Divider.Data().Dy() cx = region.X + m.layout.Name.X cy = region.Y + m.layout.Name.Y - 5 gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(cx-tdx/2, cy-tdy/2) gl.TexCoord2d(0, -1) gl.Vertex2i(cx-tdx/2, cy+(tdy+1)/2) gl.TexCoord2d(1, -1) gl.Vertex2i(cx+(tdx+1)/2, cy+(tdy+1)/2) gl.TexCoord2d(1, 0) gl.Vertex2i(cx+(tdx+1)/2, cy-tdy/2) gl.End() } if m.ent != nil && m.ent.Stats != nil { // Actions { spacing := m.layout.Actions.Icon_size * float64(m.layout.Actions.Count) spacing = m.layout.Actions.Width - spacing spacing /= float64(m.layout.Actions.Count - 1) m.state.Actions.space = spacing s := m.layout.Actions.Icon_size num_actions := len(m.ent.Actions) xpos := m.layout.Actions.X if num_actions > m.layout.Actions.Count { xpos -= m.state.Actions.scroll_pos * (s + spacing) } d := base.GetDictionary(10) var r gui.Region r.X = int(m.layout.Actions.X) r.Y = int(m.layout.Actions.Y - d.MaxHeight()) r.Dx = int(m.layout.Actions.Width) r.Dy = int(m.layout.Actions.Icon_size + d.MaxHeight()) r.PushClipPlanes() gl.Color4d(1, 1, 1, 1) for i, action := range m.ent.Actions { // Highlight the selected action if action == m.game.current_action { gl.Disable(gl.TEXTURE_2D) gl.Color4d(1, 0, 0, 1) gl.Begin(gl.QUADS) gl.Vertex3d(xpos-2, m.layout.Actions.Y-2, 0) gl.Vertex3d(xpos-2, m.layout.Actions.Y+s+2, 0) gl.Vertex3d(xpos+s+2, m.layout.Actions.Y+s+2, 0) gl.Vertex3d(xpos+s+2, m.layout.Actions.Y-2, 0) gl.End() } gl.Enable(gl.TEXTURE_2D) action.Icon().Data().Bind() if action.Preppable(m.ent, m.game) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.5, 0.5, 0.5, 1) } gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex3d(xpos, m.layout.Actions.Y, 0) gl.TexCoord2d(0, -1) gl.Vertex3d(xpos, m.layout.Actions.Y+s, 0) gl.TexCoord2d(1, -1) gl.Vertex3d(xpos+s, m.layout.Actions.Y+s, 0) gl.TexCoord2d(1, 0) gl.Vertex3d(xpos+s, m.layout.Actions.Y, 0) gl.End() gl.Disable(gl.TEXTURE_2D) ypos := m.layout.Actions.Y - d.MaxHeight() - 2 d.RenderString(fmt.Sprintf("%d", i+1), xpos+s/2, ypos, 0, d.MaxHeight(), gui.Center) xpos += spacing + m.layout.Actions.Icon_size } r.PopClipPlanes() // Now, if there is a selected action, position it between the arrows if m.state.Actions.selected != nil { // a := m.state.Actions.selected d := base.GetDictionary(15) x := m.layout.Actions.X + m.layout.Actions.Width/2 y := float64(m.layout.ActionLeft.Y) str := fmt.Sprintf("%s:%dAP", m.state.Actions.selected.String(), m.state.Actions.selected.AP()) gl.Color4d(1, 1, 1, 1) d.RenderString(str, x, y, 0, d.MaxHeight(), gui.Center) } } // Conditions { gl.Color4d(1, 1, 1, 1) c := m.layout.Conditions d := base.GetDictionary(int(c.Size)) ypos := c.Y + c.Height - d.MaxHeight() + m.state.Conditions.scroll_pos var r gui.Region r.X = int(c.X) r.Y = int(c.Y) r.Dx = int(c.Width) r.Dy = int(c.Height) r.PushClipPlanes() for _, s := range m.ent.Stats.ConditionNames() { d.RenderString(s, c.X+c.Width/2, ypos, 0, d.MaxHeight(), gui.Center) ypos -= float64(d.MaxHeight()) } r.PopClipPlanes() } // Gear if m.ent.ExplorerEnt != nil && m.ent.ExplorerEnt.Gear != nil { gear := m.ent.ExplorerEnt.Gear layout := m.layout.Gear icon := gear.Small_icon.Data() icon.RenderNatural(int(layout.X), int(layout.Y)) d := base.GetDictionary(10) d.RenderString("Gear", layout.X+float64(icon.Dx())/2, layout.Y-d.MaxHeight(), 0, d.MaxHeight(), gui.Center) } } // Mouseover text if m.state.MouseOver.active { var x int switch m.state.MouseOver.location { case mouseOverActions: x = int(m.layout.Actions.X + m.layout.Actions.Width/2) case mouseOverConditions: x = int(m.layout.Conditions.X + m.layout.Conditions.Width/2) case mouseOverGear: default: base.Warn().Printf("Got an unknown mouseover location: %d", m.state.MouseOver.location) m.state.MouseOver.active = false } y := m.layout.Background.Data().Dy() - 40 d := base.GetDictionary(15) d.RenderString(m.state.MouseOver.text, float64(x), float64(y), 0, d.MaxHeight(), gui.Center) } }
func (m *MainBar) Think(g *gui.Gui, t int64) { if g.FocusWidget() != nil { return } if m.ent != nil { // If an action is selected and we can't see it then we scroll just enough // so that we can. min := 0.0 max := float64(len(m.ent.Actions) - m.layout.Actions.Count) selected_index := -1 for i := range m.ent.Actions { if m.ent.Actions[i] == m.state.Actions.selected { selected_index = i break } } if selected_index != -1 { if min < float64(selected_index-m.layout.Actions.Count+1) { min = float64(selected_index - m.layout.Actions.Count + 1) } if max > float64(selected_index) { max = float64(selected_index) } } m.state.Actions.selected = m.game.current_action if m.state.Actions.scroll_target > max { m.state.Actions.scroll_target = max } if m.state.Actions.scroll_target < min { m.state.Actions.scroll_target = min } if m.state.Actions.clicked != nil { if m.state.Actions.selected != m.state.Actions.clicked { if m.state.Actions.clicked.Preppable(m.ent, m.game) { m.state.Actions.clicked.Prep(m.ent, m.game) m.game.SetCurrentAction(m.state.Actions.clicked) } } m.state.Actions.clicked = nil } // We similarly need to scroll through conditions c := m.layout.Conditions d := base.GetDictionary(int(c.Size)) max_scroll := d.MaxHeight() * float64(len(m.ent.Stats.ConditionNames())) max_scroll -= m.layout.Conditions.Height // This might end up with a max that is negative, but we'll cap it at zero if m.state.Conditions.scroll_pos > max_scroll { m.state.Conditions.scroll_pos = max_scroll } if m.state.Conditions.scroll_pos < 0 { m.state.Conditions.scroll_pos = 0 } } else { m.state.Conditions.scroll_pos = 0 m.state.Actions.scroll_pos = 0 m.state.Actions.scroll_target = 0 } // Do a nice scroll motion towards the target position m.state.Actions.scroll_pos *= 0.8 m.state.Actions.scroll_pos += 0.2 * m.state.Actions.scroll_target // Handle mouseover stuff after doing all of the scroll stuff since we don't // want to give a mouseover for something that the mouse isn't over after // scrolling something. m.state.MouseOver.active = false if m.ent != nil { c := m.layout.Conditions if pointInsideRect(m.mx, m.my, int(c.X), int(c.Y), int(c.Width), int(c.Height)) { pos := c.Y + c.Height + m.state.Conditions.scroll_pos - float64(m.my) index := int(pos / base.GetDictionary(int(c.Size)).MaxHeight()) if index >= 0 && index < len(m.ent.Stats.ConditionNames()) { m.state.MouseOver.active = true m.state.MouseOver.text = m.ent.Stats.ConditionNames()[index] m.state.MouseOver.location = mouseOverConditions } } if index := m.pointInsideAction(m.mx, m.my); index != -1 { m.state.MouseOver.active = true m.state.MouseOver.text = m.ent.Actions[index].String() m.state.MouseOver.location = mouseOverActions } } buttons := m.no_actions_buttons if m.ent != nil && len(m.ent.Actions) > m.layout.Actions.Count { buttons = m.all_buttons } for _, button := range buttons { button.Think(m.region.X, m.region.Y, m.mx, m.my, t) } }
func (rc *RosterChooser) Draw(r gui.Region) { rc.Render_region = r r.PushClipPlanes() defer r.PopClipPlanes() gl.Enable(gl.TEXTURE_2D) { // Up button x := r.X y := r.Y + r.Dy - rc.layout.Up.Data().Dy() rc.render.up.X = x rc.render.up.Y = y rc.render.up.Dx = rc.layout.Up.Data().Dx() rc.render.up.Dy = rc.layout.Up.Data().Dy() if rc.mouse.Inside(rc.render.up) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.8, 0.8, 0.8, 1) } rc.layout.Up.Data().RenderNatural(x, y) } { // Down button x := r.X y := r.Y + rc.layout.Down.Data().Dy() rc.render.down.X = x rc.render.down.Y = y rc.render.down.Dx = rc.layout.Down.Data().Dx() rc.render.down.Dy = rc.layout.Down.Data().Dy() if rc.mouse.Inside(rc.render.down) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.8, 0.8, 0.8, 1) } rc.layout.Down.Data().RenderNatural(x, y) } { // Options rc.render.all_options.X = r.X + rc.layout.Down.Data().Dx() rc.render.all_options.Y = r.Y + r.Dy - rc.layout.Num_options*rc.layout.Option.Dy rc.render.all_options.Dx = rc.layout.Option.Dx rc.render.all_options.Dy = rc.layout.Num_options * rc.layout.Option.Dy rc.render.all_options.PushClipPlanes() x := rc.render.all_options.X y := r.Y + r.Dy - rc.layout.Option.Dy + int(float64(rc.layout.Option.Dy)*rc.focus_pos) for i := range rc.options { rc.render.options[i] = gui.Region{ gui.Point{x, y}, gui.Dims{rc.layout.Option.Dx, rc.layout.Option.Dy}, } hovered := rc.mouse.Inside(rc.render.options[i]) selected := rc.selected[i] selectable := rc.selector(i, rc.selected, false) rc.options[i].Draw(hovered, selected, selectable, rc.render.options[i]) y -= rc.layout.Option.Dy } rc.render.all_options.PopClipPlanes() } { // Text d := base.GetDictionary(15) x := r.X y := float64(r.Y) + d.MaxHeight()/2 x1 := float64(x + r.Dx/3) x2 := float64(x + (2*r.Dx)/3) rc.render.done = gui.Region{ gui.Point{x, r.Y}, gui.Dims{r.Dx / 2, int(d.MaxHeight() * 2)}, } rc.render.undo = gui.Region{ gui.Point{x + r.Dx/2, r.Y}, gui.Dims{r.Dx / 2, int(d.MaxHeight() * 2)}, } if rc.mouse.Inside(rc.render.done) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.6, 0.6, 0.6, 1) } d.RenderString("Done", x1, y, 0, d.MaxHeight(), gui.Center) if rc.on_undo != nil { if rc.mouse.Inside(rc.render.undo) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.6, 0.6, 0.6, 1) } d.RenderString("Undo", x2, y, 0, d.MaxHeight(), gui.Center) } } }
func (sm *OnlineMenu) Think(g *gui.Gui, t int64) { if sm.last_t == 0 { sm.last_t = t return } dt := t - sm.last_t sm.last_t = t if sm.mx == 0 && sm.my == 0 { sm.mx, sm.my = gin.In().GetCursor("Mouse").Point() } done := false for !done { select { case sm.control.in <- struct{}{}: <-sm.control.out default: done = true } } var net_id mrgnet.NetId fmt.Sscanf(base.GetStoreVal("netid"), "%d", &net_id) for i := range []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted} { glb := []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted}[i] select { case list := <-glb.update: glb.games = glb.games[0:0] for j := range list.Games { var b Button var name string base.Log().Printf("Adding button: %s", list.Games[j].Name) b.Text.Justification = sm.layout.Text.Justification b.Text.Size = sm.layout.Text.Size if net_id == list.Games[j].Denizens_id { name = list.Games[j].Name } else { name = list.Games[j].Name } b.Text.String = "Join!" game_key := list.Game_keys[j] active := (glb == &sm.layout.Active) in_joingame := false b.f = func(interface{}) { if in_joingame { return } in_joingame = true if active { go func() { var req mrgnet.StatusRequest req.Id = net_id req.Game_key = game_key var resp mrgnet.StatusResponse done := make(chan bool, 1) go func() { mrgnet.DoAction("status", 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_joingame = false sm.control.out <- struct{}{} }() if resp.Err != "" || resp.Game == nil { sm.layout.Error.err = resp.Err base.Error().Printf("Couldn't join game: %v", resp.Err) return } sm.ui.RemoveChild(sm) sm.ui.AddChild(MakeGamePanel("", nil, nil, game_key)) }() } else { go func() { var req mrgnet.JoinGameRequest req.Id = net_id req.Game_key = game_key var resp mrgnet.JoinGameResponse done := make(chan bool, 1) go func() { mrgnet.DoAction("join", 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_joingame = false sm.control.out <- struct{}{} }() if resp.Err != "" || !resp.Successful { sm.layout.Error.err = resp.Err base.Error().Printf("Couldn't join game: %v", resp.Err) return } sm.ui.RemoveChild(sm) sm.ui.AddChild(MakeGamePanel("", nil, nil, game_key)) }() } } if active { d := Button{} d.Text.String = "Delete!" d.Text.Justification = "right" d.Text.Size = sm.layout.Text.Size d.f = func(interface{}) { go func() { var req mrgnet.KillRequest req.Id = net_id req.Game_key = game_key var resp mrgnet.KillResponse done := make(chan bool, 1) go func() { mrgnet.DoAction("kill", req, &resp) done <- true }() select { case <-done: case <-time.After(5 * time.Second): resp.Err = "Couldn't connect to server." } <-sm.control.in if resp.Err != "" { sm.layout.Error.err = resp.Err base.Error().Printf("Couldn't kill game: %v", resp.Err) } else { algorithm.Choose(&glb.games, func(gf gameField) bool { return gf.key != req.Game_key }) } sm.control.out <- struct{}{} }() } glb.games = append(glb.games, gameField{&b, &d, name, list.Game_keys[j], list.Games[j]}) } else { glb.games = append(glb.games, gameField{&b, nil, name, list.Game_keys[j], list.Games[j]}) } } glb.Scroll.Height = int(base.GetDictionary(sm.layout.Text.Size).MaxHeight() * float64(len(list.Games))) default: } sm.hover_game = nil if (gui.Point{sm.mx, sm.my}.Inside(glb.Scroll.Region())) { for i := range glb.games { game := &glb.games[i] var region gui.Region region.X = game.join.(*Button).bounds.x region.Y = game.join.(*Button).bounds.y region.Dx = glb.Scroll.Dx region.Dy = int(base.GetDictionary(sm.layout.Text.Size).MaxHeight()) if (gui.Point{sm.mx, sm.my}.Inside(region)) { sm.hover_game = game } game.join.Think(sm.region.X, sm.region.Y, sm.mx, sm.my, dt) if game.delete != nil { game.delete.Think(sm.region.X, sm.region.Y, sm.mx, sm.my, dt) } } } else { for _, game := range glb.games { game.join.Think(sm.region.X, sm.region.Y, 0, 0, dt) if game.delete != nil { game.delete.Think(sm.region.X, sm.region.Y, 0, 0, dt) } } } glb.Scroll.Think(dt) } if sm.update_alpha > 0.0 && time.Now().Sub(sm.update_time).Seconds() >= 2 { sm.update_alpha = doApproach(sm.update_alpha, 0.0, dt) } for _, button := range sm.buttons { button.Think(sm.region.X, sm.region.Y, sm.mx, sm.my, dt) } }