Exemplo n.º 1
0
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} {
		glb.Scroll.Region().PushClipPlanes()
		sx := glb.Scroll.X
		sy := glb.Scroll.Top() - int(d.MaxHeight())
		for _, button := range glb.games {
			button.RenderAt(sx, sy)
			sy -= int(d.MaxHeight())
		}
		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.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)
	}
}
Exemplo n.º 2
0
// 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
}
Exemplo n.º 3
0
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)
	}
}
Exemplo n.º 4
0
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
}
Exemplo n.º 5
0
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.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)
	}
}
Exemplo n.º 6
0
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)
}
Exemplo n.º 7
0
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)
	}
}
Exemplo n.º 8
0
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
}
Exemplo n.º 9
0
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()
	}
}
Exemplo n.º 10
0
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)
}
Exemplo n.º 11
0
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
}
Exemplo n.º 12
0
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()
}
Exemplo n.º 13
0
func (mo *MapOption) Draw(hovered, selected, selectable bool, region gui.Region) {
	var s byte
	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)
}
Exemplo n.º 14
0
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)
		}

	}
}
Exemplo n.º 15
0
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)
	}
}
Exemplo n.º 16
0
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)
	}
}
Exemplo n.º 17
0
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 _, glb := range []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted} {
		select {
		case list := <-glb.update:
			glb.games = glb.games[0:0]
			for i := range list.Games {
				var b Button
				base.Log().Printf("Adding button: %s", list.Games[i].Name)
				b.Text.Justification = sm.layout.Text.Justification
				b.Text.Size = sm.layout.Text.Size
				if net_id == list.Games[i].Denizens_id {
					b.Text.String = fmt.Sprintf("%s vs %s as the Intruders", list.Games[i].Name, list.Games[i].Intruders_name)
				} else {
					b.Text.String = fmt.Sprintf("%s vs %s as the Denizens", list.Games[i].Name, list.Games[i].Denizens_name)
				}
				game_key := list.Game_keys[i]
				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(10 * 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(10 * 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))
						}()
					}
				}
				glb.games = append(glb.games, &b)
			}
			sort.Sort(onlineButtonSlice(glb.games))
			glb.Scroll.Height = int(base.GetDictionary(sm.layout.Text.Size).MaxHeight() * float64(len(list.Games)))

		default:
		}

		if (gui.Point{sm.mx, sm.my}.Inside(glb.Scroll.Region())) {
			for _, button := range glb.games {
				button.Think(sm.region.X, sm.region.Y, sm.mx, sm.my, dt)
			}
		} else {
			for _, button := range glb.games {
				button.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)
	}
}
Exemplo n.º 18
0
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)
	}
}
Exemplo n.º 19
0
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.Choose2(&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)
	}
}
Exemplo n.º 20
0
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
	sm.layout.Unstarted.Scroll.Think(dt)
	if sm.mx == 0 && sm.my == 0 {
		sm.mx, sm.my = gin.In().GetCursor("Mouse").Point()
	}

	select {
	case resp := <-sm.update_user:
		sm.layout.User.Entry.text = resp.Name
		sm.update_alpha = 1.0
		sm.update_time = time.Now()
	default:
	}
	var net_id mrgnet.NetId
	fmt.Sscanf(base.GetStoreVal("netid"), "%d", &net_id)
	for _, glb := range []*gameListBox{&sm.layout.Active, &sm.layout.Unstarted} {
		select {
		case list := <-glb.update:
			glb.games = glb.games[0:0]
			for i := range list.Games {
				var b Button
				base.Log().Printf("Adding button: %s", list.Games[i].Name)
				b.Text.Justification = sm.layout.Text.Justification
				b.Text.Size = sm.layout.Text.Size
				b.Text.String = list.Games[i].Name
				b.f = func(interface{}) {
					// var req mrgnet.JoinGameRequest
					// req.Id = net_id
					// req.Game_key = list.Ids[i]
					// var resp mrgnet.JoinGameResponse
					// mrgnet.DoAction("join", req, &resp)
				}
				glb.games = append(glb.games, &b)
			}
			sort.Sort(onlineButtonSlice(glb.games))
			glb.Scroll.Height = int(base.GetDictionary(sm.layout.Text.Size).MaxHeight() * float64(len(list.Games)))

		default:
		}
		base.Log().Printf("Num: %d, region: %v", len(glb.games), glb.Scroll.Region())

		if (gui.Point{sm.mx, sm.my}.Inside(glb.Scroll.Region())) {
			for _, button := range glb.games {
				button.Think(sm.region.X, sm.region.Y, sm.mx, sm.my, dt)
			}
		} else {
			for _, button := range glb.games {
				button.Think(sm.region.X, sm.region.Y, 0, 0, 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)
	}
}