diff --git a/cmd/game/main.go b/cmd/game/main.go index 64f5aa6..aa372bf 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -85,7 +85,7 @@ func main() { //set up controller - controller := ecs.NewController() + controller := ecs.NewController(mainCtx) controller.MapComponentClass(ecs.CoordsComponent, types.Coords{}) controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{}) @@ -93,16 +93,21 @@ func main() { controller.MapComponentClass(ecs.MoveableComponent, movement.Moveable{}) controller.MapComponentClass(ecs.CarriedComponent, movement.Moveable{}) controller.MapComponentClass(ecs.UsableComponent, movement.Moveable{}) + controller.MapComponentClass(ecs.BackpackComponent, items.Backpack{}) moveable := movement.Moveable{ Controller: controller, Level: level, } + items.Init(controller) + + bp := items.Backpack{MaxMass:100, MaxBulk:100} + //Set up Screen Manager screenMgr := types.NewScreenManager(mainCtx) screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr)) - screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp, controller, screenMgr)) + screenMgr.AddScreen("game", screens.NewGameScreen(mainCtx, mw, &State, vp, controller, screenMgr)) screenMgr.AddScreen("help", screens.NewMenuScreen( mw, screenMgr, @@ -128,25 +133,20 @@ func main() { }).MakeList(), ) - screenMgr.AddScreen("inventory", screens.NewMenuScreen( - mw, - screenMgr, - "Inventory", - "Items in your backpack:", - //"[color=yellow]Note[/color]: Many of these are not implemented yet", - "", - types.NewCenteredRect(mw.Rect, 70, 25), - true, ). - SetBgColor("#ef305c70"). - SetFgColor("white"). - SetItems([]interface{}{ - `"Fish-eye" crafty shaded glasses`, - "Xecutor's glowing visor", - "Kitschy goggles of many pathways", - "Ring of inexistence", - "Orb of omniscience", - "Wand of amnesia", - }).MakeList(), + screenMgr.AddScreen("inventory", screens.InventoryScreen{ + MenuScreen: screens.NewMenuScreen( + mw, + screenMgr, + "Inventory", + "Items in your backpack:", + //"[color=yellow]Note[/color]: Many of these are not implemented yet", + "", + types.NewCenteredRect(mw.Rect, 70, 25), + true, ). + SetBgColor("#ef305c70"). + SetFgColor("white"). + SetItems([]interface{}{}).MakeList() + }, ) screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen( @@ -174,7 +174,9 @@ func main() { controller.AddComponent(player, rooms[0].Center) //implicit Coords controller.AddComponent(player, moveable) + controller.AddComponent(player, bp) + //fixme adding items potion := controller.CreateEntity([]ecs.Component{}) controller.AddComponent(potion, types.Appearance{ Glyph: types.PlainGlyphHolder{"!"}, @@ -182,11 +184,24 @@ func main() { Fg: types.PlainColorHolder{255, 55, 255, 222}, }, }) - controller.AddComponent(potion, rooms[1].Center) //implicit Coords - controller.AddComponent(potion, items.Carried{}) + controller.AddComponent(potion, rooms[0].Center) //implicit Coords + controller.AddComponent(potion, items.Carried{Mass:5, Bulk:3}) controller.AddComponent(potion, items.Usable{}) controller.AddComponent(potion, items.Consumable{}) + potion2 := controller.CreateEntity([]ecs.Component{}) + controller.AddComponent(potion2, types.Appearance{ + Glyph: types.PlainGlyphHolder{"!"}, + ColorSet: types.TileColorSet{ + Fg: types.PlainColorHolder{255, 222, 255, 55}, + }, + }) + controller.AddComponent(potion2, rooms[1].Center) //implicit Coords + controller.AddComponent(potion2, items.Carried{Mass:5, Bulk:3}) + controller.AddComponent(potion2, items.Usable{}) + controller.AddComponent(potion2, items.Consumable{}) + //fixme end setting up items + State.Player = player State.Controller = controller diff --git a/engine/ecs/controller.go b/engine/ecs/controller.go index d736cec..68eeb8e 100644 --- a/engine/ecs/controller.go +++ b/engine/ecs/controller.go @@ -3,11 +3,13 @@ package ecs // ECS system by jcerise, github.com/jcerise/gogue import ( - "fmt" + "context" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" "sort" ) type Controller struct { + ctx context.Context systems map[string]System sortedSystems map[int][]System priorityKeys []int @@ -21,8 +23,8 @@ type Controller struct { } // NewController is a convenience/constructor method to properly initialize a new processor -func NewController() *Controller { - controller := Controller{} +func NewController(ctx context.Context) *Controller { + controller := Controller{ctx: ctx} controller.systems = make(map[string]System) controller.sortedSystems = make(map[int][]System) controller.priorityKeys = []int{} @@ -78,7 +80,7 @@ func (c *Controller) GetMappedComponentClass(componentName string) Component { return c.componentMap[componentName] } else { // TODO: Add better (read: actual) error handling here - fmt.Printf("Component[%s] not registered on Controller.\n", componentName) + appctx.Logger(c.ctx).Warn().Msgf("Component[%s] not registered on Controller.\n", componentName) return nil } } @@ -206,7 +208,7 @@ func (c *Controller) AddSystem(system System, priority int) { c.sortedSystems[priority] = append(c.sortedSystems[priority], system) sort.Ints(c.priorityKeys) } else { - fmt.Printf("A system of type %v was already added to the controller %v!", systemType, c) + appctx.Logger(c.ctx).Warn().Msgf("A system of type %v was already added to the controller %v!", systemType, c) } } diff --git a/engine/ecs/system.go b/engine/ecs/system.go index b8fbba0..773418f 100644 --- a/engine/ecs/system.go +++ b/engine/ecs/system.go @@ -2,8 +2,7 @@ package ecs // ECS system by jcerise, github.com/jcerise/gogue -const MobRenderSystem = "mobrender" -const TerrainRenderSystem = "terrainrender" +const TerrainRenderSystem = "levelrender" type System interface { Process() diff --git a/engine/ecs/systems/level_render_system.go b/engine/ecs/systems/level_render_system.go new file mode 100644 index 0000000..3bccb88 --- /dev/null +++ b/engine/ecs/systems/level_render_system.go @@ -0,0 +1,160 @@ +package systems + +import ( + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + "lab.zaar.be/thefish/alchemyst-go/engine/fov" + "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "sort" + "time" +) + +var fovRecompute = true +var redraw = false + +type LevelRenderSystem struct { + Viewport *mainwindow.ViewPort + Controller *ecs.Controller + state *gamestate.GameState + layer *mainwindow.Layer + fov fov.Fov + animateTiles *time.Ticker + TorchRadius int +} + +func NewLevelRenderSystem( + state *gamestate.GameState, + controller *ecs.Controller, + vp *mainwindow.ViewPort, + layer *mainwindow.Layer, + fov fov.Fov, +) LevelRenderSystem { + + trs := LevelRenderSystem{ + Viewport: vp, + Controller: controller, + layer: layer, + state: state, + fov: fov, + } + + trs.TorchRadius = 12 //fixme move to sight component + + trs.animateTiles = time.NewTicker(time.Second / 12) + + return trs +} + +//fixme add to screens/game Exit() +func (trs LevelRenderSystem) Close() { + trs.animateTiles.Stop() + trs.animateTiles = nil //zero pointer to ticker +} + +func (trs LevelRenderSystem) Listen() { + for { + select { + case <-trs.state.FovRecompute: + fovRecompute = true + case <-trs.state.Redraw: + redraw = true + case <-trs.animateTiles.C: + redraw = true + } + } +} + +type priorityRenderable struct { + types.Appearance + types.Coords + Priority int //with bigger are rendered last +} + +type prioritySorter []priorityRenderable + +func (a prioritySorter) Len() int { return len(a) } +func (a prioritySorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a prioritySorter) Less(i, j int) bool { return a[i].Priority < a[j].Priority } + +func (trs LevelRenderSystem) Process() { + playerCoords := trs.state.Controller.GetComponent(trs.state.Player, ecs.CoordsComponent).(types.Coords) + + trs.Viewport.Move(trs.state, playerCoords) + + if fovRecompute { + trs.layer.ClearRect(trs.Viewport.Rect) + trs.fov.ComputeFov(trs.state.Level, playerCoords, trs.TorchRadius) + fovRecompute = false + redraw = true + } + + if redraw { + //terrain + for y := 0; y < trs.Viewport.H; y++ { + for x := 0; x < trs.Viewport.W; x++ { + mapCoords := types.Coords{trs.Viewport.CameraCoords.X + x, trs.Viewport.CameraCoords.Y + y} + + if trs.state.Level.InBounds(mapCoords) { + tile := trs.state.Level.GetTile(mapCoords) + if tile.Explored || tile.Visible { + trs.layer.PutToBase( + x+trs.Viewport.X, + y+trs.Viewport.Y, + tile.GetChar(), + tile.GetRawColor(), + tile.GetRawBgColor(), + ) + } + } + } + } + + //mobs + entToRender := make([]priorityRenderable, 0) + for e := range trs.Controller.GetEntities() { + if trs.Controller.HasComponent(e, ecs.CoordsComponent) && + trs.Controller.HasComponent(e, ecs.AppearanceComponent) { + + pos := trs.Controller.GetComponent(e, ecs.CoordsComponent).(types.Coords) + appearance := trs.Controller.GetComponent(e, ecs.AppearanceComponent).(types.Appearance) + + //fixme fov check + if !trs.state.Level.GetTile(pos).Visible { + continue + } + + vpc, err := trs.Viewport.ToVPCoords(pos) + if err != nil { + continue //we cant see it? no problem. + } + //Костыль для приоритета отрисовки + p := 0 + if trs.Controller.HasComponent(e, ecs.CarriedComponent) { + p = 10 + } + if trs.Controller.HasComponent(e, ecs.MoveableComponent) { + p = 100 + } + + entToRender = append(entToRender, priorityRenderable{ + Appearance: appearance, + Coords: vpc, + Priority: p, + }) + } + } + sort.Sort(prioritySorter(entToRender)) + + for _, ree := range entToRender { + trs.layer.WithRawColor(ree.Appearance.ColorSet.Fg.GetColor()). + Put(ree.X, ree.Y, ree.Appearance.Glyph.GetGlyph()) + } + entToRender = nil + redraw = false + } +} + +func (trs LevelRenderSystem) SystemType() string { + return ecs.TerrainRenderSystem +} diff --git a/engine/ecs/systems/mob_render_system.go b/engine/ecs/systems/mob_render_system.go deleted file mode 100644 index 786ecf5..0000000 --- a/engine/ecs/systems/mob_render_system.go +++ /dev/null @@ -1,45 +0,0 @@ -package systems - -import ( - "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - "lab.zaar.be/thefish/alchemyst-go/engine/fov" - "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" - "lab.zaar.be/thefish/alchemyst-go/engine/types" - "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" -) - -type MobRenderSystem struct { - Controller *ecs.Controller - Layer *mainwindow.Layer - Viewport *mainwindow.ViewPort - Fov fov.Fov - *gamemap.Level -} - -func (mrs MobRenderSystem) Process() { - //if redraw { - for e := range mrs.Controller.GetEntities() { - if mrs.Controller.HasComponent(e, ecs.CoordsComponent) && - mrs.Controller.HasComponent(e, ecs.AppearanceComponent) { - - pos := mrs.Controller.GetComponent(e, ecs.CoordsComponent).(types.Coords) - appearance := mrs.Controller.GetComponent(e, ecs.AppearanceComponent).(types.Appearance) - - //fixme fov check - //if !mrs.Fov.IsInFov(pos) { - // continue - //} - - vpc, err := mrs.Viewport.ToVPCoords(pos) - if err != nil { - continue //we cant see it? no problem. - } - mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(vpc.X, vpc.Y, appearance.Glyph.GetGlyph()) - } - } - //} -} - -func (mrs MobRenderSystem) SystemType() string { - return ecs.MobRenderSystem -} diff --git a/engine/ecs/systems/terrain_render_system.go b/engine/ecs/systems/terrain_render_system.go deleted file mode 100644 index a5fa89f..0000000 --- a/engine/ecs/systems/terrain_render_system.go +++ /dev/null @@ -1,104 +0,0 @@ -package systems - -import ( - "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - "lab.zaar.be/thefish/alchemyst-go/engine/fov" - "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" - "lab.zaar.be/thefish/alchemyst-go/engine/types" - "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" - "time" -) - -var fovRecompute = true -var redraw = false - - -type TerrainRenderSystem struct { - Viewport *mainwindow.ViewPort - state *gamestate.GameState - layer *mainwindow.Layer - fov fov.Fov - animateTiles *time.Ticker - TorchRadius int -} - -func NewTerrainRenderSystem( - state *gamestate.GameState, - vp *mainwindow.ViewPort, - layer *mainwindow.Layer, - fov fov.Fov, -) TerrainRenderSystem { - - trs := TerrainRenderSystem{ - Viewport:vp, - layer: layer, - state: state, - fov: fov, - } - - trs.TorchRadius = 12 //fixme move to sight component - - trs.animateTiles = time.NewTicker(time.Second / 12) - - - return trs -} - -//fixme add to screens/game Exit() -func (trs TerrainRenderSystem) Close() { - trs.animateTiles.Stop() - trs.animateTiles = nil //zero pointer to ticker -} - -func (trs TerrainRenderSystem) Listen() { - for { - select { - case <-trs.state.FovRecompute: - fovRecompute = true - case <-trs.state.Redraw: - redraw = true - case <-trs.animateTiles.C: - redraw = true - } - } -} - -func (trs TerrainRenderSystem) Process() { - playerCoords := trs.state.Controller.GetComponent(trs.state.Player, ecs.CoordsComponent).(types.Coords) - - trs.Viewport.Move(trs.state, playerCoords) - - if fovRecompute { - trs.layer.ClearRect(trs.Viewport.Rect) - trs.fov.ComputeFov(trs.state.Level, playerCoords, trs.TorchRadius) - fovRecompute = false - redraw = true - } - - if redraw { - //terrain - for y := 0; y < trs.Viewport.H; y++ { - for x := 0; x < trs.Viewport.W; x++ { - mapCoords := types.Coords{trs.Viewport.CameraCoords.X + x, trs.Viewport.CameraCoords.Y + y} - - if trs.state.Level.InBounds(mapCoords) { - tile := trs.state.Level.GetTile(mapCoords) - if tile.Explored || tile.Visible { - trs.layer.PutToBase( - x+trs.Viewport.X, - y+trs.Viewport.Y, - tile.GetChar(), - tile.GetRawColor(), - tile.GetRawBgColor(), - ) - } - } - } - } - redraw = false - } -} - -func (trs TerrainRenderSystem) SystemType() string { - return ecs.TerrainRenderSystem -} \ No newline at end of file diff --git a/engine/fov/precomputed_shade/precomputed_shade.go b/engine/fov/precomputed_shade/precomputed_shade.go index 55ef27c..4123033 100644 --- a/engine/fov/precomputed_shade/precomputed_shade.go +++ b/engine/fov/precomputed_shade/precomputed_shade.go @@ -124,6 +124,7 @@ func (ps *precomputedShade) FindByCoords(c types.Coords) (int, *Cell, error) { func (ps *precomputedShade) IsInFov(coords types.Coords) bool { rc := ps.fromLevelCoords(coords) + if rc.X == 0 && rc.Y ==0 {return true} _, cell, err := ps.FindByCoords(rc) if err != nil { return false diff --git a/engine/items/backpack.go b/engine/items/backpack.go index d611980..c3e2a0f 100644 --- a/engine/items/backpack.go +++ b/engine/items/backpack.go @@ -30,4 +30,8 @@ func (b *Backpack) HasFreeSpace(Bulk, Mass int) bool { return false } return true +} + +func (b *Backpack) GetItems() []ecs.Entity { + return b.items } \ No newline at end of file diff --git a/engine/items/carried.go b/engine/items/carried.go index 7e8c9aa..9df2123 100644 --- a/engine/items/carried.go +++ b/engine/items/carried.go @@ -50,6 +50,8 @@ func (c Carried) Pickup(who, what ecs.Entity) { //remove coords instead (does not exist on map anymore) Controller.RemoveComponent(what, ecs.CoordsComponent) bp.items = append(bp.items, what) + //fuck that, we need to update constantly + Controller.UpdateComponent(who, ecs.BackpackComponent, bp) } func (c Carried) Drop(who, what ecs.Entity) { @@ -87,11 +89,12 @@ func (c *Carried) GetBulk(what ecs.Entity) int { return c.Bulk } -func FindCarriedOnTile(coords types.Coords) []ecs.Entity { +func FindCarriedUnder(who ecs.Entity) []ecs.Entity { + coords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) result := make([]ecs.Entity, 0) for _, ent := range carrieds { - car := Controller.GetComponent(ent, ecs.CarriedComponent) + car := Controller.GetComponent(ent, ecs.CoordsComponent) if car == coords { result = append(result, ent) } diff --git a/engine/items/common.go b/engine/items/common.go index d774f2c..b5cc484 100644 --- a/engine/items/common.go +++ b/engine/items/common.go @@ -2,8 +2,8 @@ package items import "lab.zaar.be/thefish/alchemyst-go/engine/ecs" -var Controller ecs.Controller +var Controller *ecs.Controller -func Init(ctrl ecs.Controller) { +func Init(ctrl *ecs.Controller) { Controller = ctrl } \ No newline at end of file diff --git a/engine/screens/game.go b/engine/screens/game.go index d080447..d46393e 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -1,45 +1,47 @@ package screens import ( + "context" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/ecs/systems" "lab.zaar.be/thefish/alchemyst-go/engine/fov" "lab.zaar.be/thefish/alchemyst-go/engine/fov/precomputed_shade" "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" + "lab.zaar.be/thefish/alchemyst-go/engine/items" "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" ) type GameScreen struct { + ctx context.Context mw *mainwindow.MainWindow state *gamestate.GameState vp *mainwindow.ViewPort controller *ecs.Controller scm *types.ScreenManager - fov fov.Fov + fov fov.Fov } -func NewGameScreen(mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen { - ts := &GameScreen{mw: mw, state: state, vp: viewPort, controller: controller, scm: scm} +func NewGameScreen(ctx context.Context, mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen { + ts := &GameScreen{ + ctx: ctx, + mw: mw, + state: state, + vp: viewPort, + controller: controller, + scm: scm, + } //fixme move this to fov system computedFov := precomputed_shade.NewPrecomputedShade(15) computedFov.Init() ts.fov = computedFov - renderMobs := systems.MobRenderSystem{ - Controller: ts.controller, - Layer: ts.mw.GetLayer("base"), - Viewport: ts.vp, - Level: state.Level, - Fov: ts.fov, - } - ts.controller.AddSystem(renderMobs, 10) - renderTerrain := systems.NewTerrainRenderSystem(state, viewPort, ts.mw.GetLayer("base"), ts.fov) - go renderTerrain.Listen() - ts.controller.AddSystem(renderTerrain, 5) - + renderLevel := systems.NewLevelRenderSystem(state, ts.controller, viewPort, ts.mw.GetLayer("base"), ts.fov) + go renderLevel.Listen() + ts.controller.AddSystem(renderLevel, 50) return ts } @@ -50,8 +52,8 @@ func (ts *GameScreen) Enter() { Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help") } func (ts *GameScreen) Exit() { - //trs := ts.controller.GetSystem(ecs.TerrainRenderSystem) - //trs.(systems.TerrainRenderSystem).Close() + //trs := ts.controller.GetSystem(ecs.LevelRenderSystem) + //trs.(systems.LevelRenderSystem).Close() ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3) //remove what we dont need } @@ -90,6 +92,23 @@ func (ts *GameScreen) HandleInput(input string) { ts.scm.SetScreenByName("devmenu") break + case "g": + //get list of carriables on tile + carrieds := items.FindCarriedUnder(ts.state.Player) + if len(carrieds) == 0 { + break + } //do nothing + //select if there is more than 1 + if len(carrieds) > 1 { + appctx.Logger(ts.ctx).Warn().Msg("Passing item list to inventory not implemented yet") + } else { + //call pickup in selected + cc := items.Controller.GetComponent(carrieds[0], ecs.CarriedComponent).(items.Carried) + items.Carried.Pickup(cc, ts.state.Player, carrieds[0]) + } + + break; + case "i": ts.scm.SetScreenByName("inventory") break @@ -104,4 +123,4 @@ func (ts *GameScreen) HandleInput(input string) { func (ts *GameScreen) Render() { //ts.vp.Render(ts.state) ts.controller.Process([]string{}) -} \ No newline at end of file +} diff --git a/engine/screens/inventory.go b/engine/screens/inventory.go index 6b19c5a..e08ac2b 100644 --- a/engine/screens/inventory.go +++ b/engine/screens/inventory.go @@ -1,11 +1,99 @@ package screens -type InventoryScreen struct { +import ( + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "strings" +) +type InventoryScreen struct { + *MenuScreen + items []ecs.Entity + + cursor int + offset int + pageSize int } -func (ts *InventoryScreen) UseEcs() bool {return true} -func (ts *InventoryScreen) Enter() {} -func (ts *InventoryScreen) HandleInput(input string) {} -func (ts *InventoryScreen) Exit() {} -func (ts *InventoryScreen) Render() {} +func (is *InventoryScreen) MakeInverntory() *InventoryScreen { + is.drawFunc = is.InventoryRender + is.inputFunc = is.HandleInput + return is +} + +func (is *InventoryScreen) SetItems(items []ecs.Entity) *InventoryScreen { + is.items = items + return is +} + +func (is *InventoryScreen) HandleInput(input string) { + switch input { + 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.items)-1 { + is.offset = len(is.items) - 1 + } + break + case "enter": + //select current under cursor + break; + case "a","b","c","d","e","f","g","h","i","j","k","l": + //selct by letter + 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{is.X, is.Y + headerHeight + 1, is.W, is.H - headerHeight - footerHeight} + _ = itemField + var ilw, ilh int + if (len(is.items) > 0) { + //fixme itemfield object, scroller, inputhandler, current selected item + menuItems := make([]string, 0) + for i := is.offset; i < len(is.items); i++ { + if string(is.items[i].(string)) != "" { + menuItems = append(menuItems, is.items[i].(string)) + } + } + ilw, ilh = menuLayer.PrintInside(itemField, strings.Join(menuItems, "\n"), blt.TK_ALIGN_LEFT) + } + if ilh < len(is.items) { + is.drawScrollBar(menuLayer, itemField) + } + if ilw > itemField.W-4 { + fmt.Printf("Excess width of item names found! Need h-scroll of certain names") + } +} + + +//func (ms *InventoryScreen) UseEcs() bool {return true} +//func (ms *InventoryScreen) Enter() {} + +//func (ms *InventoryScreen) Exit() {} +//func (ms *InventoryScreen) Render() {}