alchemyst/engine/screens/inventory.go
2024-04-22 13:52:17 +03:00

191 lines
4.4 KiB
Go

package screens
import (
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/items"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
blt "lab.zaar.be/thefish/bearlibterminal"
"strings"
)
type InventoryScreen struct {
*MenuScreen
who ecs.Entity
cursor int
offset int
pageSize int
selected []int
prepared preparedList
}
type displayItem struct {
Entity ecs.Entity
Name string
Index string
Selected bool
}
type preparedList []displayItem
func (p *preparedList) Prepare(is *InventoryScreen) {
//fixme add item class sorting
bp := items.Controller.GetComponent(is.who, ecs.BackpackComponent).(items.Backpack)
is.prepared = make([]displayItem, len(bp.GetItems()))
//prepare item list
for i, ent := range bp.GetItems() {
namec := items.Controller.GetComponent(ent, ecs.Named{}.Type()).(ecs.Named)
is.prepared[i] = displayItem{
Entity: ent,
Name: namec.Name,
Index: string(runeIndex[i]),
}
}
}
func (is *InventoryScreen) MakeInverntory(who ecs.Entity) *InventoryScreen {
is.drawFunc = is.InventoryRender
is.inputFunc = is.HandleInput
is.who = who
return is
}
func (is *InventoryScreen) Enter() {
is.redraw = true
is.offset = 0
is.cursor = 0
is.prepared = preparedList{}
is.prepared.Prepare(is)
}
//fixme key names to action constants!
//fixme unify scrolling controls!
func (is *InventoryScreen) HandleInput(input string) {
if strings.Contains(string(runeIndex), strings.Replace(input, "Shift+", "", -1)) {
if strings.Contains("Shift+", input) {
input = strings.ToUpper(input)
}
for i, _ := range is.prepared {
if is.prepared[i].Index == input {
is.prepared[i].Selected = !is.prepared[i].Selected
}
}
return
}
switch input {
case "Up", "k":
is.cursor = is.cursor - 1
if is.cursor < 0 {
is.cursor = 0
}
if is.cursor < is.offset {
is.offset = is.offset - 1
if is.offset < 0 {
is.offset = 0
}
}
break
case "Down", "j":
is.cursor = is.cursor + 1
if is.cursor >= len(is.prepared) {
is.cursor = len(is.prepared) - 1
}
if is.cursor > is.offset {
is.offset = is.offset + 1
if is.offset*is.pageSize > len(is.prepared) {
is.offset = len(is.prepared) / is.pageSize
}
}
break
case "Left":
is.prepared[is.cursor].Selected = false
break
case "Right":
is.prepared[is.cursor].Selected = true
break
case "PageUp":
is.offset = is.offset - 1
if is.offset < 0 {
is.offset = 0
}
break
case "PageDown":
is.offset = is.offset + 1
if is.offset > len(is.prepared)-1 {
is.offset = len(is.prepared) - 1
}
break
case "enter":
//show actions menu for item under cursor
//fixme implement
break;
case "Escape":
fallthrough
case "Space":
is.scm.SetScreen(is.scm.PreviousScreen)
break
}
}
func (is *InventoryScreen) InventoryRender() {
menuLayer := is.mw.GetLayer("menu")
menuLayer.ClearRect(is.Rect)
bgLayer := is.mw.GetLayer("menubg")
bgLayer.ClearRect(is.Rect)
bgLayer.WithColor(is.bgColor).NewWindow(is.Rect).Splash()
menuLayer.WithColor(is.fgColor).NewWindow(is.Rect).DoubleBordered(is.title)
menuLayer.Print(is.X+(is.W/2)-7, is.Y+is.H-1, "╡"+"[color=green]Space[/color] to close"+"╞")
footerHeight := 0
if is.footer != "" {
_, footerHeight = menuLayer.PrintInside(is.Rect, is.footer, 9)
footerHeight = footerHeight + 2
}
_, headerHeight := menuLayer.PrintInside(is.Rect, is.header, blt.TK_ALIGN_LEFT)
itemField := types.Rect{
X: is.X,
Y: is.Y + headerHeight + 1,
W: is.W,
H: is.H - headerHeight - footerHeight,
}
_ = itemField
is.pageSize = itemField.H - 2
if (len(is.prepared) > 0) {
for i := is.offset; i < itemField.H; i++ {
if i < len(is.prepared) {
selectedColor := "white"
selectedDash := "-"
if is.prepared[i].Selected {
selectedColor = "green"
selectedDash = "+"
}
if is.cursor == i {
menuLayer.WithColor("yellow")
} else {
menuLayer.WithColor("white")
}
menuStr := fmt.Sprintf("[color=%s]%s[/color] %s %s", selectedColor, is.prepared[i].Index, selectedDash, is.prepared[i].Name)
if len(menuStr) > itemField.W - 2 {
menuStr = menuStr[0:itemField.W - 2]
}
menuLayer.PutStringInto(itemField,i,menuStr,1)
}
}
}
if is.cursor < len(is.prepared) {
is.drawScrollBar(menuLayer, itemField)
}
}
//func (ms *InventoryScreen) UseEcs() bool {return true}
//func (ms *InventoryScreen) Enter() {}
//func (ms *InventoryScreen) Exit() {}
//func (ms *InventoryScreen) Render() {}