func setWaypoint(gp *GamePanel) lua.GoFunction { return func(L *lua.State) int { if !LuaCheckParamsOk(L, "SetWaypoint", LuaString, LuaString, LuaPoint, LuaFloat) { return 0 } gp.script.syncStart() defer gp.script.syncEnd() var wp waypoint side_str := L.ToString(-3) switch side_str { case "intruders": wp.Side = SideExplorers case "denizens": wp.Side = SideHaunt default: base.Error().Printf("Specified '%s' for the side parameter in SetWaypoint, must be 'intruders' or 'denizens'.", side_str) return 0 } wp.Name = L.ToString(-4) // Remove any existing waypoint by the same name algorithm.Choose2(&gp.game.Waypoints, func(w waypoint) bool { return w.Name != wp.Name }) px, py := LuaToPoint(L, -2) wp.X = float64(px) wp.Y = float64(py) wp.Radius = L.ToNumber(-1) gp.game.Waypoints = append(gp.game.Waypoints, wp) return 0 } }
func (a *AoeAttack) getTargetsAt(g *game.Game, tx, ty int) []*game.Entity { x := tx - (a.Diameter+1)/2 y := ty - (a.Diameter+1)/2 x2 := tx + a.Diameter/2 y2 := ty + a.Diameter/2 // If the diameter is even we need to run los from all four positions // around the center of the aoe. num_centers := 1 if a.Diameter%2 == 0 { num_centers = 4 } var targets []*game.Entity for i := 0; i < num_centers; i++ { // If num_centers is 4 then this will calculate the los for all four // positions around the center g.DetermineLos(tx+i%2, ty+i/2, a.Diameter, grid[i]) } for _, ent := range g.Ents { entx, enty := ent.Pos() has_los := false for i := 0; i < num_centers; i++ { has_los = has_los || grid[i][entx][enty] } if has_los && entx >= x && entx < x2 && enty >= y && enty < y2 { targets = append(targets, ent) } } algorithm.Choose2(&targets, func(e *game.Entity) bool { return e.Stats != nil }) return targets }
func (w *WallPanel) onEscape() { if w.wall_texture != nil { if w.prev_wall_texture != nil { *w.wall_texture = *w.prev_wall_texture } else { algorithm.Choose2(&w.room.WallTextures, func(wt *WallTexture) bool { return wt != w.wall_texture }) } } w.wall_texture = nil w.prev_wall_texture = nil }
func (w *FurniturePanel) onEscape() { if w.furniture != nil { if w.prev_object != nil { *w.furniture = *w.prev_object w.prev_object = nil } else { algorithm.Choose2(&w.Room.Furniture, func(f *Furniture) bool { return f != w.furniture }) } w.furniture = nil } }
func (hdt *houseRelicsTab) onEscape() { if hdt.temp_relic != nil { if hdt.prev_relic != nil { *hdt.temp_relic = *hdt.prev_relic hdt.prev_relic = nil } else { algorithm.Choose2(&hdt.house.Floors[0].Spawns, func(s *SpawnPoint) bool { return s != hdt.temp_relic }) } hdt.temp_relic = nil } }
func (w *WallPanel) Respond(ui *gui.Gui, group gui.EventGroup) bool { if w.VerticalTable.Respond(ui, group) { return true } if found, event := group.FindEvent(gin.DeleteOrBackspace); found && event.Type == gin.Press { algorithm.Choose2(&w.room.WallTextures, func(wt *WallTexture) bool { return wt != w.wall_texture }) w.wall_texture = nil w.prev_wall_texture = nil return true } if found, event := group.FindEvent(gin.Escape); found && event.Type == gin.Press { w.onEscape() return true } if found, event := group.FindEvent(base.GetDefaultKeyMap()["flip"].Id()); found && event.Type == gin.Press { if w.wall_texture != nil { w.wall_texture.Flip = !w.wall_texture.Flip } return true } if found, event := group.FindEvent(gin.MouseWheelVertical); found { if w.wall_texture != nil && gin.In().GetKey(gin.Space).CurPressAmt() == 0 { w.wall_texture.Rot += float32(event.Key.CurPressAmt() / 100) } } if found, event := group.FindEvent(gin.MouseLButton); found && event.Type == gin.Press { if w.wall_texture != nil { w.wall_texture.temporary = false w.wall_texture = nil } else if w.wall_texture == nil { w.wall_texture = w.textureNear(event.Key.Cursor().Point()) if w.wall_texture != nil { w.prev_wall_texture = new(WallTexture) *w.prev_wall_texture = *w.wall_texture w.wall_texture.temporary = true wx, wy := w.viewer.BoardToWindowf(w.wall_texture.X, w.wall_texture.Y) px, py := event.Key.Cursor().Point() w.drag_anchor.X = float32(px) - wx w.drag_anchor.Y = float32(py) - wy } } return true } return false }
func Chooser2Spec(c gospec.Context) { c.Specify("Choose on []int", func() { a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} b := make([]int, len(a)) copy(b, a) algorithm.Choose2(&b, func(v int) bool { return v%2 == 0 }) c.Expect(b, ContainsInOrder, []int{0, 2, 4, 6, 8}) b = make([]int, len(a)) copy(b, a) algorithm.Choose2(&b, func(v int) bool { return v%2 == 1 }) c.Expect(b, ContainsInOrder, []int{1, 3, 5, 7, 9}) b = make([]int, len(a)) copy(b, a) algorithm.Choose2(&b, func(v int) bool { return true }) c.Expect(b, ContainsInOrder, a) b = make([]int, len(a)) copy(b, a) algorithm.Choose2(&b, func(v int) bool { return false }) c.Expect(b, ContainsInOrder, []int{}) b = b[0:0] algorithm.Choose2(&b, func(v int) bool { return false }) c.Expect(b, ContainsInOrder, []int{}) }) c.Specify("Choose on []string", func() { a := []string{"foo", "bar", "wing", "ding", "monkey", "machine"} b := make([]string, len(a)) copy(b, a) algorithm.Choose2(&b, func(v string) bool { return v > "foo" }) c.Expect(b, ContainsInOrder, []string{"wing", "monkey", "machine"}) b = make([]string, len(a)) copy(b, a) algorithm.Choose2(&b, func(v string) bool { return v < "foo" }) c.Expect(b, ContainsInOrder, []string{"bar", "ding"}) b = make([]string, len(a)) copy(b, a) algorithm.Choose2(&b, func(v string) bool { return true }) c.Expect(b, ContainsInOrder, a) }) }
func (hdt *houseRelicsTab) Respond(ui *gui.Gui, group gui.EventGroup) bool { if hdt.VerticalTable.Respond(ui, group) { return true } if found, event := group.FindEvent(gin.Escape); found && event.Type == gin.Press { hdt.onEscape() return true } if found, event := group.FindEvent(gin.DeleteOrBackspace); found && event.Type == gin.Press { algorithm.Choose2(&hdt.house.Floors[0].Spawns, func(s *SpawnPoint) bool { return s != hdt.temp_relic }) hdt.temp_relic = nil hdt.prev_relic = nil return true } cursor := group.Events[0].Key.Cursor() floor := hdt.house.Floors[hdt.current_floor] if found, event := group.FindEvent(gin.MouseLButton); found && event.Type == gin.Press { if hdt.temp_relic != nil { if !hdt.temp_relic.invalid { hdt.temp_relic.temporary = false hdt.temp_relic = nil } } else { for _, sp := range floor.Spawns { fbx, fby := hdt.viewer.WindowToBoard(cursor.Point()) bx, by := roundDown(fbx), roundDown(fby) x, y := sp.Pos() dx, dy := sp.Dims() if bx >= x && bx < x+dx && by >= y && by < y+dy { hdt.temp_relic = sp hdt.prev_relic = new(SpawnPoint) *hdt.prev_relic = *hdt.temp_relic hdt.temp_relic.temporary = true hdt.drag_anchor.x = fbx - float32(hdt.temp_relic.X) hdt.drag_anchor.y = fby - float32(hdt.temp_relic.Y) break } } } } return false }
func (hdt *houseDoorTab) onEscape() { if hdt.temp_door != nil { if hdt.temp_room != nil { algorithm.Choose2(&hdt.temp_room.Doors, func(d *Door) bool { return d != hdt.temp_door }) } if hdt.prev_door != nil { hdt.prev_room.Doors = append(hdt.prev_room.Doors, hdt.prev_door) hdt.prev_door.state.pos = -1 // forces it to redo its gl data hdt.prev_door = nil hdt.prev_room = nil } hdt.temp_door = nil hdt.temp_room = nil } }
func (hdt *houseDataTab) onEscape() { if hdt.prev_room != nil { dx := hdt.prev_room.X - hdt.temp_room.X dy := hdt.prev_room.Y - hdt.temp_room.Y for i := range hdt.temp_spawns { hdt.temp_spawns[i].X += dx hdt.temp_spawns[i].Y += dy } *hdt.temp_room = *hdt.prev_room hdt.prev_room = nil } else { algorithm.Choose2(&hdt.house.Floors[0].Rooms, func(r *Room) bool { return r != hdt.temp_room }) } hdt.temp_room = nil }
func (e *Entity) SetGear(gear_name string) bool { if e.ExplorerEnt == nil { base.Error().Printf("Tried to set gear on a non-explorer entity.") return false } if e.ExplorerEnt.Gear != nil && gear_name != "" { base.Error().Printf("Tried to set gear on an explorer that already had gear.") return false } if e.ExplorerEnt.Gear == nil && gear_name == "" { base.Error().Printf("Tried to remove gear from an explorer with no gear.") return false } if gear_name == "" { algorithm.Choose2(&e.Actions, func(a Action) bool { return a.String() != e.ExplorerEnt.Gear.Action }) if e.ExplorerEnt.Gear.Condition != "" { e.Stats.RemoveCondition(e.ExplorerEnt.Gear.Condition) } e.ExplorerEnt.Gear = nil return true } var g Gear g.Defname = gear_name base.GetObject("gear", &g) if g.Name == "" { base.Error().Printf("Tried to load gear '%s' that doesn't exist.", gear_name) return false } e.ExplorerEnt.Gear = &g if g.Action != "" { e.Actions = append(e.Actions, MakeAction(g.Action)) } if g.Condition != "" { e.Stats.ApplyCondition(status.MakeCondition(g.Condition)) } return true }
func (hv *HouseViewer) RemoveDrawable(d Drawable) { algorithm.Choose2(&hv.drawables, func(t Drawable) bool { return t != d }) }
func (hdt *houseDoorTab) Respond(ui *gui.Gui, group gui.EventGroup) bool { if hdt.VerticalTable.Respond(ui, group) { return true } if found, event := group.FindEvent(gin.Escape); found && event.Type == gin.Press { hdt.onEscape() return true } if found, event := group.FindEvent(gin.DeleteOrBackspace); found && event.Type == gin.Press { algorithm.Choose2(&hdt.temp_room.Doors, func(d *Door) bool { return d != hdt.temp_door }) hdt.temp_room = nil hdt.temp_door = nil hdt.prev_room = nil hdt.prev_door = nil return true } cursor := group.Events[0].Key.Cursor() var bx, by float32 if cursor != nil { bx, by = hdt.viewer.WindowToBoard(cursor.Point()) } if cursor != nil && hdt.temp_door != nil { room := hdt.viewer.FindClosestDoorPos(hdt.temp_door, bx, by) if room != hdt.temp_room { algorithm.Choose2(&hdt.temp_room.Doors, func(d *Door) bool { return d != hdt.temp_door }) hdt.temp_room = room hdt.temp_door.invalid = (hdt.temp_room == nil) hdt.temp_room.Doors = append(hdt.temp_room.Doors, hdt.temp_door) } if hdt.temp_room == nil { hdt.temp_door.invalid = true } else { other_room, _ := hdt.house.Floors[0].findRoomForDoor(hdt.temp_room, hdt.temp_door) hdt.temp_door.invalid = (other_room == nil) } } floor := hdt.house.Floors[hdt.current_floor] if found, event := group.FindEvent(gin.MouseLButton); found && event.Type == gin.Press { if hdt.temp_door != nil { other_room, other_door := floor.findRoomForDoor(hdt.temp_room, hdt.temp_door) if other_room != nil { other_room.Doors = append(other_room.Doors, other_door) hdt.temp_door.temporary = false hdt.temp_door = nil hdt.prev_door = nil } } else { hdt.temp_room, hdt.temp_door = hdt.viewer.FindClosestExistingDoor(bx, by) if hdt.temp_door != nil { hdt.prev_door = new(Door) *hdt.prev_door = *hdt.temp_door hdt.prev_room = hdt.temp_room hdt.temp_door.temporary = true room, door := hdt.house.Floors[0].FindMatchingDoor(hdt.temp_room, hdt.temp_door) if room != nil { algorithm.Choose2(&room.Doors, func(d *Door) bool { return d != door }) } } } return true } return false }
func (hdt *houseDataTab) Respond(ui *gui.Gui, group gui.EventGroup) bool { if hdt.VerticalTable.Respond(ui, group) { return true } if found, event := group.FindEvent(gin.Escape); found && event.Type == gin.Press { hdt.onEscape() return true } if found, event := group.FindEvent(gin.DeleteOrBackspace); found && event.Type == gin.Press { if hdt.temp_room != nil { spawns := make(map[*SpawnPoint]bool) for i := range hdt.temp_spawns { spawns[hdt.temp_spawns[i]] = true } algorithm.Choose2(&hdt.house.Floors[0].Spawns, func(s *SpawnPoint) bool { return !spawns[s] }) algorithm.Choose2(&hdt.house.Floors[0].Rooms, func(r *Room) bool { return r != hdt.temp_room }) hdt.temp_room = nil hdt.prev_room = nil hdt.viewer.SetBounds() } return true } floor := hdt.house.Floors[hdt.current_floor] if found, event := group.FindEvent(gin.MouseLButton); found && event.Type == gin.Press { if hdt.temp_room != nil { if !hdt.temp_room.invalid { hdt.temp_room.temporary = false floor.removeInvalidDoors() hdt.temp_room = nil hdt.prev_room = nil hdt.viewer.SetBounds() } } else { cx, cy := event.Key.Cursor().Point() bx, by := hdt.viewer.WindowToBoard(cx, cy) for i := range floor.Rooms { x, y := floor.Rooms[i].Pos() dx, dy := floor.Rooms[i].Dims() if int(bx) >= x && int(bx) < x+dx && int(by) >= y && int(by) < y+dy { hdt.temp_room = floor.Rooms[i] hdt.prev_room = new(Room) *hdt.prev_room = *hdt.temp_room hdt.temp_room.temporary = true hdt.drag_anchor.x = bx - float32(x) hdt.drag_anchor.y = by - float32(y) break } } if hdt.temp_room != nil { hdt.temp_spawns = hdt.temp_spawns[0:0] for _, sp := range hdt.house.Floors[0].Spawns { x, y := sp.Pos() rx, ry := hdt.temp_room.Pos() rdx, rdy := hdt.temp_room.Dims() if x >= rx && x < rx+rdx && y >= ry && y < ry+rdy { hdt.temp_spawns = append(hdt.temp_spawns, sp) } } } } return true } return false }
// This is called if the player is ready to end the turn, if the turn ends // then the following things happen: // 1. The game script gets to run its OnRound() function // 2. Entities with stats and HpCur() <= 0 are removed. // 3. Entities all have their OnRound() function called. func (g *Game) OnRound() { // Don't end the round if any of the following are true // An action is currently executing if g.Action_state != noAction { return } // Any master ai is still active if g.Side == SideHaunt && (g.Ai.minions.Active() || g.Ai.denizens.Active()) { return } g.Turn++ if g.Side == SideExplorers { g.Side = SideHaunt } else { g.Side = SideExplorers } g.viewer.Los_tex.Remap() for i := range g.Ents { if g.Ents[i].Side() == g.Side { g.Ents[i].OnRound() } } // The entity ais must be activated before the master ais, otherwise the // masters might be running with stale data if one of the entities has been // reloaded. for i := range g.Ents { g.Ents[i].Ai.Activate() base.Log().Printf("EntityActive '%s': %t", g.Ents[i].Name, g.Ents[i].Ai.Active()) } if g.Side == SideHaunt { g.Ai.minions.Activate() g.Ai.denizens.Activate() g.player_inactive = g.Ai.denizens.Active() } else { g.Ai.intruders.Activate() g.player_inactive = g.Ai.intruders.Active() } for i := range g.Ents { if g.Ents[i].Stats != nil && g.Ents[i].Stats.HpCur() <= 0 { g.viewer.RemoveDrawable(g.Ents[i]) } } algorithm.Choose2(&g.Ents, func(ent *Entity) bool { return ent.Stats == nil || ent.Stats.HpCur() > 0 }) g.script.OnRound(g) if g.selected_ent != nil { g.selected_ent.hovered = false g.selected_ent.selected = false } if g.hovered_ent != nil { g.hovered_ent.hovered = false g.hovered_ent.selected = false } g.hovered_ent = nil }
func (hv *HouseViewer) RemoveFloorDrawable(fd FloorDrawer) { algorithm.Choose2(&hv.floor_drawers, func(t FloorDrawer) bool { return t != fd }) }
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) } }
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.Choose2(&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 }
func (w *FurniturePanel) Respond(ui *gui.Gui, group gui.EventGroup) bool { if w.VerticalTable.Respond(ui, group) { return true } // On escape we want to revert the furniture we're moving back to where it was // and what state it was in before we selected it. If we don't have any // furniture selected then we don't do anything. if found, event := group.FindEvent(gin.Escape); found && event.Type == gin.Press { w.onEscape() return true } // If we hit delete then we want to remove the furniture we're moving around // from the room. If we're not moving anything around then nothing happens. if found, event := group.FindEvent(gin.DeleteOrBackspace); found && event.Type == gin.Press { algorithm.Choose2(&w.Room.Furniture, func(f *Furniture) bool { return f != w.furniture }) w.furniture = nil w.prev_object = nil return true } if found, event := group.FindEvent(w.key_map["rotate left"].Id()); found && event.Type == gin.Press { if w.furniture != nil { w.furniture.RotateLeft() } } if found, event := group.FindEvent(w.key_map["rotate right"].Id()); found && event.Type == gin.Press { if w.furniture != nil { w.furniture.RotateRight() } } if found, event := group.FindEvent(w.key_map["flip"].Id()); found && event.Type == gin.Press { if w.furniture != nil { w.furniture.Flip = !w.furniture.Flip } } if found, event := group.FindEvent(gin.MouseLButton); found && event.Type == gin.Press { if w.furniture != nil { if !w.furniture.invalid { w.furniture.temporary = false w.furniture = nil } } else if w.furniture == nil { bx, by := w.RoomViewer.WindowToBoard(event.Key.Cursor().Point()) for i := range w.Room.Furniture { x, y := w.Room.Furniture[i].Pos() dx, dy := w.Room.Furniture[i].Dims() if int(bx) >= x && int(bx) < x+dx && int(by) >= y && int(by) < y+dy { w.furniture = w.Room.Furniture[i] w.prev_object = new(Furniture) *w.prev_object = *w.furniture w.furniture.temporary = true px, py := w.furniture.Pos() w.drag_anchor.x = bx - float32(px) w.drag_anchor.y = by - float32(py) break } } } return true } return false }