package levels import ( "sort" mgl "github.com/go-gl/mathgl/mgl32" "github.com/inkyblackness/hacked/ss1/content/archive/level" ) type hoverItem interface { Pos() MapPosition Size() float32 IsIn(lvl *level.Level) bool } type tileHoverItem struct { pos MapPosition } func (item tileHoverItem) Pos() MapPosition { return item.pos } func (item tileHoverItem) Size() float32 { return level.FineCoordinatesPerTileSide } func (item tileHoverItem) IsIn(lvl *level.Level) bool { return lvl.Tile(item.pos.Tile()) != nil } type objectHoverItem struct { id level.ObjectID pos MapPosition } func (item objectHoverItem) Pos() MapPosition { return item.pos } func (item objectHoverItem) Size() float32 { return level.FineCoordinatesPerTileSide / 4 } func (item objectHoverItem) IsIn(lvl *level.Level) bool { obj := lvl.Object(item.id) return (obj != nil) && (obj.InUse != 0) && (item.pos.X == obj.X) && (item.pos.Y == obj.Y) } type hoverItems struct { available []hoverItem activeIndex int activeItem hoverItem } func (items *hoverItems) reset() { items.available = nil items.activeIndex = 0 items.activeItem = nil } func (items *hoverItems) scroll(forward bool) { count := len(items.available) if count > 0 { diff := 1 if !forward { diff = -1 } items.activeIndex = (count + (items.activeIndex + diff)) % count items.activeItem = items.available[items.activeIndex] } } func (items *hoverItems) find(lvl *level.Level, pos MapPosition) { refVec := mgl.Vec2{float32(pos.X), float32(pos.Y)} var distances []float32 items.available = nil lvl.ForEachObject(func(id level.ObjectID, entry level.ObjectMainEntry) { entryVec := mgl.Vec2{float32(entry.X), float32(entry.Y)} distance := refVec.Sub(entryVec).Len() if distance < level.FineCoordinatesPerTileSide/4 { items.available = append(items.available, objectHoverItem{ id: id, pos: MapPosition{X: entry.X, Y: entry.Y}, }) distances = append(distances, distance) } }) items.available = append(items.available, tileHoverItem{ pos: MapPosition{ X: level.CoordinateAt(pos.X.Tile(), level.FineCoordinatesPerTileSide/2), Y: level.CoordinateAt(pos.Y.Tile(), level.FineCoordinatesPerTileSide/2), }, }) distances = append(distances, level.FineCoordinatesPerTileSide) sort.Slice(items.available, func(a, b int) bool { return distances[a] < distances[b] }) items.activeIndex = 0 items.activeItem = items.available[items.activeIndex] } func (items *hoverItems) validate(lvl *level.Level) { allValid := true for _, item := range items.available { if !item.IsIn(lvl) { allValid = false break } } if allValid { return } newItems := make([]hoverItem, 0, len(items.available)) for index, item := range items.available { isActive := index == items.activeIndex if item.IsIn(lvl) { if isActive { items.activeIndex = len(newItems) } newItems = append(newItems, item) } else if isActive { items.activeIndex = 0 } } items.available = newItems items.activeItem = nil if items.activeIndex < len(items.available) { items.activeItem = items.available[items.activeIndex] } }