Replace info panel with topbar

This commit is contained in:
cbeimers113
2025-01-31 22:21:24 -05:00
parent 38578f0d28
commit 9bd63e0932
24 changed files with 205 additions and 110 deletions

14
TODO.md
View File

@@ -1,16 +1,22 @@
### v0.2.1:
- [x] Space & control to go vertically up and down
- [x] Limit how far from map we can go
- [ ] Tab to play/pause
- [ ] Toolbar instead of info panel
- [ ] Reset position on new sim
- [ ] Fix autosave bug/persistent plants issue
- [ ] Fullscreen option in config
- [ ] GUI scale option in config
- [ ] Fix mouse jittering bug when going in and out of menus
- [ ] Pipeline improvements / build & release binaries / auto-tagging
- [ ] Auto updates
- [ ] Skybox
- [ ] Shadows
- [ ] Revisit tile highlighting
- [ ] Fix bug with conservation of mass (water)
- [x] Toggle info panel for chemical quantities in top right
- [x] Notifications appear in bottom left
- [x] Topbar instead of info panel
- [x] Space & control to go vertically up and down
- [x] Limit how far from map we can go
- [x] Tab to play/pause
### v0.3.0 - Plants Upgrade:

View File

@@ -66,16 +66,16 @@ func (n *NotificationManager) Render() {
}
n.noteObjects = make([]*gui.Label, 0)
width, _ := n.app.GetSize()
_, height := n.app.GetSize()
// Add labels to screen for notifications
for i, note := range n.notifications {
alpha := color.Opaque.A * min(note.timer, LIMIT/2) / (LIMIT / 2)
alpha := color.Translucent.A * min(note.timer, LIMIT/2) / (LIMIT / 2)
fgCol := &math32.Color4{R: 0.0, G: 0.0, B: 0.0, A: alpha}
bgCol := &math32.Color4{R: 1.0, G: 1.0, B: 1.0, A: alpha}
obj := gui.NewLabel(note.message)
y := float32(i)*obj.Height() + 10*float32(i+1)
obj.SetPosition(float32(width)-obj.Width()-15, y)
y := float32(height) - float32(i+1) * (obj.Height() + 10)
obj.SetPosition(5, y)
obj.SetPaddings(0, 5, 0, 5)
obj.SetColor4(fgCol)
obj.SetBgColor4(bgCol)

View File

@@ -146,13 +146,9 @@ func (p *Plant) Update() {
p.SetPosition(p.X, 0.5+p.Scale().Y/2, p.Z)
}
// Infostring returns a string representation of the tile
// Infostring returns a string representation of the plant
func (p Plant) InfoString() string {
infoString := "Plant:\n"
infoString += fmt.Sprintf("age=%d\n", p.Age)
infoString += fmt.Sprintf("colour=#%06x", p.Colour)
return infoString
return fmt.Sprintf("plant,  : %dt,  : #%06x", p.Age, p.Colour)
}
// Material returns the plant's material

View File

@@ -292,14 +292,14 @@ func (t *Tile) AddPlant(entities map[int]Entity, scene *core.Node) bool {
// Infostring returns a string representation of the tile
func (t Tile) InfoString() string {
infoString := "Tile:\n"
infoString += fmt.Sprintf("type=%s\n", t.Type.Name)
infoString += fmt.Sprintf("temperature=%s\n", t.Temperature)
infoString += fmt.Sprintf("water level=%s\n", t.WaterLevel)
infoString += fmt.Sprintf("elevation=%s\n", t.getElevation())
infoString += fmt.Sprintf("planted=%t", len(t.Plants) > 0)
return infoString
return fmt.Sprintf(
"%s, : %s,  : %s,  : %s,  : %d",
t.Type.Name,
t.Temperature,
t.WaterLevel,
t.getElevation(),
len(t.Plants),
)
}
// Material returns the tile's material

View File

@@ -12,35 +12,45 @@ import (
)
const (
// Gui
TexMenuLogo = "menuLogo"
TexCursor = "cursor"
TexDirt = "dirt"
TexGrass = "grass"
TexSand = "sand"
TexSeed = "seed"
TexStalk = "stalk"
TexStone = "stone"
TexWater = "water"
TexWalk = "walk"
TexRun = "run"
// World
TexDirt = "dirt"
TexGrass = "grass"
TexSand = "sand"
TexSeed = "seed"
TexStalk = "stalk"
TexStone = "stone"
TexWater = "water"
)
var (
//go:embed textures/menuLogo.png
//go:embed textures/gui/menuLogo.png
bytesMenuLogo []byte
//go:embed textures/cursor.png
//go:embed textures/gui/cursor.png
bytesCursor []byte
//go:embed textures/dirt.png
//go:embed textures/gui/walk.png
bytesWalk []byte
//go:embed textures/gui/run.png
bytesRun []byte
//go:embed textures/world/dirt.png
bytesDirt []byte
//go:embed textures/grass.png
//go:embed textures/world/grass.png
bytesGrass []byte
//go:embed textures/sand.png
//go:embed textures/world/sand.png
bytesSand []byte
//go:embed textures/seed.png
//go:embed textures/world/seed.png
bytesSeed []byte
//go:embed textures/stalk.png
//go:embed textures/world/stalk.png
bytesStalk []byte
//go:embed textures/stone.png
//go:embed textures/world/stone.png
bytesStone []byte
//go:embed textures/water.png
//go:embed textures/world/water.png
bytesWater []byte
)
@@ -55,6 +65,9 @@ func init() {
}{
{id: TexMenuLogo, data: bytesMenuLogo},
{id: TexCursor, data: bytesCursor},
{id: TexWalk, data: bytesWalk},
{id: TexRun, data: bytesRun},
{id: TexDirt, data: bytesDirt},
{id: TexGrass, data: bytesGrass},
{id: TexSand, data: bytesSand},

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -11,5 +11,5 @@ var (
White = &math32.Color{R: 1.00, G: 1.00, B: 1.00}
Black = &math32.Color{R: 0.00, G: 0.00, B: 0.00}
Opaque = &math32.Color4{R: 1.00, G: 1.00, B: 1.00, A: 0.75}
Translucent = &math32.Color4{R: 1.00, G: 1.00, B: 1.00, A: 0.50}
)

View File

@@ -51,6 +51,7 @@ type Gui struct {
// Main menu components
menuLogo *gui.Image
versionLabel *gui.Label
startButton *gui.Button
newButton *gui.Button
settingsButton *gui.Button
@@ -71,9 +72,14 @@ type Gui struct {
saveButton *gui.Button
// Simulation view components
simCursor *gui.Image
infoLabel *gui.Label
pausedLabel *gui.Label
simCursor *gui.Image
topPanel *gui.Panel
moveIcon *gui.Image
playerLabel *gui.Label
clockLabel *gui.Label
wailaLabel *gui.Label
quantitiesLabel *gui.Label
helpLabel *gui.Label
// Tile context menu components
tileInfoLabel *gui.Label

View File

@@ -64,6 +64,12 @@ func (g *Gui) registerMainMenu() {
g.menuLogo.SetPosition((float32(width)-lw)/2, (g.startButton.Position().Y-lh)/2)
g.menuLogo.SetUserData(MainMenu)
g.Scene.Add(g.menuLogo)
g.versionLabel = gui.NewLabel(fmt.Sprintf("Version %s", g.Version))
g.versionLabel.SetColor(color.Green)
g.versionLabel.SetUserData(MainMenu)
g.versionLabel.SetPosition((float32(width)-g.versionLabel.Width())/2, g.menuLogo.Position().Y+g.menuLogo.Height()+5)
g.Scene.Add(g.versionLabel)
}
g.newButton = gui.NewButton("New Simulation")
@@ -159,6 +165,7 @@ func (g *Gui) registerMainMenu() {
g.closeBrowseDialog()
g.Scene.Remove(g.menuLogo)
g.Scene.Remove(g.versionLabel)
g.Scene.Remove(g.startButton)
g.Scene.Remove(g.newButton)
g.Scene.Remove(g.saveButton)

View File

@@ -2,6 +2,7 @@ package gui
import (
"fmt"
"strings"
"github.com/g3n/engine/gui"
"github.com/g3n/engine/texture"
@@ -38,88 +39,136 @@ func (g *Gui) registerSimulationView() {
g.Scene.Add(g.simCursor)
}
g.infoLabel = gui.NewLabel(g.infoText())
g.infoLabel.SetColor(color.Black)
g.infoLabel.SetBgColor4(color.Opaque)
g.infoLabel.SetPosition(5, 5)
g.infoLabel.SetUserData(SimulationView)
g.infoLabel.SetPaddings(5, 5, 5, 5)
g.Scene.Add(g.infoLabel)
g.topPanel = gui.NewPanel(float32(width), 20)
g.topPanel.SetColor4(color.Translucent)
g.topPanel.SetUserData(SimulationView)
g.Scene.Add(g.topPanel)
g.pausedLabel = gui.NewLabel(g.pausedStatus())
g.pausedLabel.SetColor(color.Black)
g.pausedLabel.SetBgColor4(color.Opaque)
g.pausedLabel.SetPosition((float32(width)-g.pausedLabel.Width())/2, 5)
g.pausedLabel.SetUserData(SimulationView)
g.pausedLabel.SetPaddings(5, 5, 5, 5)
g.Scene.Add(g.pausedLabel)
g.moveIcon = gui.NewImageFromTex(graphics.Textures[graphics.TexWalk])
g.moveIcon.SetUserData(SimulationView)
g.Scene.Add(g.moveIcon)
g.playerLabel = gui.NewLabel(g.playerPos())
g.playerLabel.SetColor(color.Black)
g.playerLabel.SetUserData(SimulationView)
g.Scene.Add(g.playerLabel)
g.clockLabel = gui.NewLabel(g.getClock())
g.clockLabel.SetColor(color.Black)
g.clockLabel.SetUserData(SimulationView)
g.Scene.Add(g.clockLabel)
g.wailaLabel = gui.NewLabel(g.getWaila())
g.wailaLabel.SetColor(color.Black)
g.wailaLabel.SetUserData(SimulationView)
g.Scene.Add(g.wailaLabel)
g.helpLabel = gui.NewLabel(helpText())
g.helpLabel.SetColor(color.Black)
g.helpLabel.SetBgColor4(color.Translucent)
g.helpLabel.SetPosition(5, 25)
g.helpLabel.SetUserData(SimulationView)
g.helpLabel.SetPaddings(5, 5, 5, 5)
g.Scene.Add(g.helpLabel)
g.quantitiesLabel = gui.NewLabel(g.getQuantities())
g.quantitiesLabel.SetColor(color.Black)
g.quantitiesLabel.SetBgColor4(color.Translucent)
g.quantitiesLabel.SetPosition(5, 25)
g.quantitiesLabel.SetUserData(SimulationView)
g.quantitiesLabel.SetPaddings(5, 5, 5, 5)
g.Scene.Add(g.quantitiesLabel)
g.State.SetInMenu(false)
},
close: func() {
g.Scene.Remove(g.simCursor)
g.Scene.Remove(g.infoLabel)
g.Scene.Remove(g.pausedLabel)
g.Scene.Remove(g.topPanel)
g.Scene.Remove(g.moveIcon)
g.Scene.Remove(g.playerLabel)
g.Scene.Remove(g.clockLabel)
g.Scene.Remove(g.wailaLabel)
g.Scene.Remove(g.helpLabel)
g.Scene.Remove(g.quantitiesLabel)
},
refresh: func() {
width, _ := g.App.GetSize()
g.infoLabel.SetText(g.infoText())
g.pausedLabel.SetText(g.pausedStatus())
g.pausedLabel.SetPosition((float32(width)-g.pausedLabel.Width())/2, 5)
g.moveIcon.SetPosition(0, 0)
g.playerLabel.SetText(g.playerPos())
g.playerLabel.SetPosition(g.moveIcon.Width(), 1)
g.clockLabel.SetText(g.getClock())
g.clockLabel.SetPosition((float32(width)-g.clockLabel.Width())/2, 1)
g.wailaLabel.SetText(g.getWaila())
g.wailaLabel.SetPosition(float32(width)-g.wailaLabel.Width()-4, 1)
g.helpLabel.SetVisible(g.Cfg.ShowHelp)
g.quantitiesLabel.SetVisible(g.State.ShowChems())
g.quantitiesLabel.SetText(g.getQuantities())
g.quantitiesLabel.SetPosition(float32(width)-g.quantitiesLabel.Width()-5, 25)
if g.State.FastMovement() {
g.moveIcon.SetTexture(graphics.Textures[graphics.TexRun])
} else {
g.moveIcon.SetTexture(graphics.Textures[graphics.TexWalk])
}
},
}
}
// Load the info text
func (g *Gui) infoText() string {
txt := fmt.Sprintf("Version %s\n", g.Version)
txt += fmt.Sprintf("TPS: %d\n", g.State.TPS())
txt += fmt.Sprintf("%s\n", g.State.Clock)
txt += "\n"
if g.Cfg.ShowHelp {
txt += "Controls:\n"
txt += "WASD to move\n"
txt += "Hold shift to move faster\n"
txt += "Caps lock to toggle fast movement\n"
txt += "Space and CTRL to go up and down\n"
txt += "ESC to open menu\n"
txt += "Tab to play/pause simulation\n"
txt += "Left click a tile to add 10 L of water\n"
txt += "Right click a tile to open the tile menu\n"
}
// Append info about simulation
txt += "\nChemical Levels:\n"
for name, amnt := range g.State.Quantities {
txt += fmt.Sprintf("%s: %s\n", name, amnt.String())
}
// Append player info
// Get the player's position
func (g *Gui) playerPos() string {
p := g.Cam.Position()
if g.State.FastMovement() {
txt += "\nFast Move"
return fmt.Sprintf("(%d, %d, %d)", int32(p.X), int32(p.Y), int32(p.Z))
}
// Get the in-game clock
func (g *Gui) getClock() string {
playPause := ""
if g.State.Paused() {
playPause = ""
}
txt += fmt.Sprintf("\n(%d, %d, %d)", int32(p.X), int32(p.Y), int32(p.Z))
return fmt.Sprintf(" %s | %d t/s | %s ", g.State.Clock, g.State.TPS(), playPause)
}
// Append the WAILA (what am I looking at?) data
// Get the WAILA info
func (g *Gui) getWaila() string {
if g.State.LookingAt != nil {
txt += "\n\nLooking At:\n"
txt += g.State.LookingAt.InfoString()
return g.State.LookingAt.InfoString()
}
return ""
}
// Get the help text
func helpText() string {
txt := "Controls:\n"
txt += " WASD to move\n"
txt += " Hold shift to move faster\n"
txt += " Caps lock to toggle fast movement\n"
txt += " Space and CTRL to go up and down\n"
txt += " ESC to open menu\n"
txt += " Tab to play/pause simulation\n"
txt += " Q to toggle chemical quantities panel\n"
txt += " Left click a tile to add 10 L of water\n"
txt += " Right click a tile to open the tile menu\n"
txt += "\nThis message can be toggled in the settings menu!"
return txt
}
// Update the "Simulation Running/Paused" status
func (g *Gui) pausedStatus() string {
suffix := "Running"
if g.State.Paused() {
suffix = "Paused"
// Get chemical quantities
func (g *Gui) getQuantities() string {
txt := "Chemical Levels:\n"
for name, amnt := range g.State.Quantities {
txt += fmt.Sprintf("%s: %s\n", name, amnt.String())
}
return fmt.Sprintf("Simulation %s", suffix)
return strings.TrimSpace(txt)
}

View File

@@ -32,7 +32,7 @@ func (g *Gui) registerTileContextMenu() {
g.tileInfoLabel.SetPosition((float32(width)-w)/2, (float32(height)-h)/2)
g.tileInfoLabel.SetUserData(TileContextMenu)
g.tileInfoLabel.SetColor(color.Black)
g.tileInfoLabel.SetBgColor4(color.Opaque)
g.tileInfoLabel.SetBgColor4(color.Translucent)
g.tileInfoLabel.SetPaddings(5, 5, 5, 5)
g.Scene.Add(g.tileInfoLabel)
nextY = g.tileInfoLabel.Position().Y + g.tileInfoLabel.Height() + 5

View File

@@ -84,6 +84,10 @@ func (i *InputManager) KeyDown(evname string, ev interface{}) {
i.dx = 0.01
case window.KeyA:
i.dx = -0.01
case window.KeyQ:
if !i.State.InMenu() {
i.State.SetShowChems(!i.State.ShowChems())
}
case window.KeyLeftShift:
i.shift = true
case window.KeyCapsLock:

View File

@@ -13,11 +13,12 @@ import (
// Represent the game state
type State struct {
tps int // Record the number of world ticks per second
inMenu bool // Whether the player is in a menu and everything in the simulation is frozen, including the player
inMainMenu bool // Whether the main menu is open
paused bool // Whether the simulation physics are paused, but the player can still interact with the simulation
fastMove bool // Whether the player is using fast movement
tps int // Record the number of world ticks per second
showChems bool // Whether to show the levels of each chemical in the simulation
Seed int64 // The world's random seed value
Rand *rand.Rand // The simulation's psuedo random number generator
@@ -29,6 +30,8 @@ type State struct {
func New(cfg *config.Config, seed int64) *State {
return &State{
showChems: true,
Seed: seed,
Rand: rand.New(rand.NewSource(seed)),
Clock: NewClock(cfg, 9, 00, true),
@@ -37,6 +40,13 @@ func New(cfg *config.Config, seed int64) *State {
}
}
// region setters
// Set the number of ticks per second
func (s *State) SetTPS(tps int) {
s.tps = tps
}
// Set the inMenu state
func (s *State) SetInMenu(inMenu bool) {
s.inMenu = inMenu
@@ -58,9 +68,16 @@ func (s *State) SetFastMovement(fast bool) {
s.fastMove = fast
}
// Set the number of ticks per second
func (s *State) SetTPS(tps int) {
s.tps = tps
// Set whether we are showing chemical quantities
func (s *State) SetShowChems(showChems bool) {
s.showChems = showChems
}
// region getters
// Get the number of ticks per second
func (s State) TPS() int {
return s.tps
}
// Get the inMenu state
@@ -83,9 +100,9 @@ func (s State) FastMovement() bool {
return s.fastMove
}
// Get the number of ticks per second
func (s State) TPS() int {
return s.tps
// Get whether we are showing chemical quantities
func (s State) ShowChems() bool {
return s.showChems
}
// Get the entity associated with a node, return nil if there isn't one

View File

@@ -17,9 +17,6 @@ func main() {
fmt.Printf("Warning: non-semantic version number provided: %s\n", Version)
}
// TODO: remove this tag if doing a release/automated build
Version += " snapshot"
cfg, err := config.Load()
if err != nil {
panic(err)