summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rw-r--r--engine/UI/Button.go3
-rw-r--r--engine/UI/FlexElement.go70
-rw-r--r--engine/UI/GridColumn.go26
-rw-r--r--engine/UI/GridRow.go75
-rw-r--r--engine/UI/Label.go3
-rw-r--r--engine/UI/Menu.go54
-rw-r--r--engine/UI/Style.go9
-rw-r--r--engine/main.go15
8 files changed, 204 insertions, 51 deletions
diff --git a/engine/UI/Button.go b/engine/UI/Button.go
index 8d336a9..a8b9168 100644
--- a/engine/UI/Button.go
+++ b/engine/UI/Button.go
@@ -22,6 +22,9 @@ type Button struct {
func (base *Button) Init(parent *Menu) {
base.DisplayElement.Init(parent)
+ if base.WidthWeight == 0 {
+ base.WidthWeight = 1
+ }
switch base.EventType {
case OnClick:
diff --git a/engine/UI/FlexElement.go b/engine/UI/FlexElement.go
new file mode 100644
index 0000000..233b89f
--- /dev/null
+++ b/engine/UI/FlexElement.go
@@ -0,0 +1,70 @@
+package ui
+
+import rl "github.com/gen2brain/raylib-go/raylib"
+
+// A dynamically shrinking element that contains other elements
+type flexElement interface {
+ GetElements() []UIElement
+ GetSpacing() float32
+ RecalculateCache(*rl.Rectangle)
+}
+
+// Calculates the element weight to pixel ratio
+func getWeightToPixelsRatio(base flexElement, totalSpace float32) float32 {
+ var elements = base.GetElements()
+ var totalWeights float32 = 0
+ for _, v := range elements {
+ totalWeights += v.GetOccupationWeight()
+ }
+ var spacingPx = totalSpace * base.GetSpacing()
+ var totalSpacing = float32(len(elements) - 1) * spacingPx
+ if totalSpace < 0 {
+ totalSpace = 0
+ }
+ return (totalSpace - totalSpacing) / totalWeights
+}
+
+
+type layoutCache struct {
+ // The screen resolution the cache was calculated for
+ ScreenResolution rl.Vector2
+ // The resolution the cache was calculated for
+ SpanResolution rl.Vector2
+ // Horizontal offset in pixels
+ OffsetX float32
+ // Vertical offset in pixels
+ OffsetY float32
+ // The X size of a row
+ Width float32
+ // The Y size of a row
+ Height float32
+ // The horizontal start and end of each row.
+ // Index of an array is representive with row index
+ RowLocations []rl.Vector2
+}
+
+func (base layoutCache) IsValid() bool {
+ return base.ScreenResolution.X == float32(rl.GetScreenWidth()) &&
+ base.ScreenResolution.Y == float32(rl.GetScreenHeight())
+}
+
+func (base *layoutCache) CalculateOffsets(X float32, Y float32, paddingX float32, paddingY float32) {
+ base.OffsetX = (X * paddingX)
+ base.OffsetY = (Y * paddingY)
+ base.Width = X - base.OffsetX * 2
+ base.Height = Y - base.OffsetY * 2
+}
+
+func (base *layoutCache) CalculateRowsLocations (rows []UIElement, WeightToPixels float32, spacing float32, baseOffset float32) {
+ base.RowLocations = make([]rl.Vector2, len(rows))
+ var ptr float32 = baseOffset
+ for i, v := range rows {
+ // The spacing should be accounted for in the WeightToPixels param
+ var elemSpace = (WeightToPixels * v.GetOccupationWeight())
+ base.RowLocations[i] = rl.Vector2 {
+ X: ptr,
+ Y: elemSpace,
+ }
+ ptr += elemSpace + spacing
+ }
+}
diff --git a/engine/UI/GridColumn.go b/engine/UI/GridColumn.go
new file mode 100644
index 0000000..02d441f
--- /dev/null
+++ b/engine/UI/GridColumn.go
@@ -0,0 +1,26 @@
+package ui
+
+import rl "github.com/gen2brain/raylib-go/raylib"
+
+type GridColumn struct {
+ Weight float32
+ Spacing float32
+ Elements []UIElement
+
+ cache layoutCache
+}
+
+func (base *GridColumn) Init(*Menu) {
+}
+
+func (base *GridColumn) Destroy() {
+}
+
+// Gets the scale width of the element. Works similar to CSS's 'flex-grow'
+func (base *GridColumn) GetOccupationWeight() float32 {
+ return base.Weight
+}
+
+// Draw the element with the given size
+func (base *GridColumn) Draw(*rl.Rectangle) {
+}
diff --git a/engine/UI/GridRow.go b/engine/UI/GridRow.go
index bb9ffe3..4e222a7 100644
--- a/engine/UI/GridRow.go
+++ b/engine/UI/GridRow.go
@@ -1,25 +1,90 @@
package ui
-import rl "github.com/gen2brain/raylib-go/raylib"
+import (
+ "image/color"
+
+ rl "github.com/gen2brain/raylib-go/raylib"
+)
+
+var defaultGridPadding float32 = 0
+var defaultGridRoundness float32 = 0
+
+var defaultGridStyle = &Style {
+ BacgroundColor: &color.RGBA{0, 0, 0, 0},
+ FontColor: &rl.DarkGray,
+ Padding: &defaultGridPadding,
+ Roundness: &defaultGridRoundness,
+}
type GridRow struct {
// A portion of the screen the row will occupy. Works similar to CSS's 'flex-grow'
HeightWeight float32
// The objects that lay in this row
Objects []UIElement
+ // Spaces between the columns
+ Spacing float32
+ // Styling preferences
+ Style *Style
location rl.Rectangle
+ cache layoutCache
+}
+
+func (base *GridRow) GetElements() []UIElement {
+ return base.Objects
+}
+
+func (base *GridRow) GetSpacing() float32 {
+ return base.Spacing
}
func (base *GridRow) Init(parent *Menu) {
+ base.Style = InitStyle(base.Style, defaultGridStyle)
for _, v := range base.Objects {
v.Init(parent)
}
+ base.cache = layoutCache {
+ ScreenResolution: rl.Vector2{ X:0, Y:0 },
+ }
}
-func (base *GridRow) Draw(span rl.Rectangle) {
- // TODO: Add horizontal spacing
- for _, v := range base.Objects {
- v.Draw(&span)
+func (base *GridRow) Destroy() {
+}
+
+// Gets the scale width of the element. Works similar to CSS's 'flex-grow'
+func (base *GridRow) GetOccupationWeight() float32 {
+ return base.HeightWeight
+}
+
+// Draw the element with the given size
+func (base *GridRow) Draw(span *rl.Rectangle) {
+ if !base.cache.IsValid() {
+ base.RecalculateCache(span)
+ }
+ for i, v := range base.Objects {
+ var offset = base.cache.RowLocations[i]
+ var elemSpan = rl.Rectangle {
+ X: offset.X,
+ Y: span.Y + *base.Style.Padding,
+ Width: offset.Y,
+ Height: span.Height - *base.Style.Padding * 2,
+ }
+ v.Draw(&elemSpan)
+ }
+}
+
+func (base *GridRow) RecalculateCache(span *rl.Rectangle) {
+ base.cache.SpanResolution = rl.Vector2{
+ X: span.Width,
+ Y: span.Height,
+ }
+ base.cache.ScreenResolution = rl.Vector2 {
+ X: float32(rl.GetScreenWidth()),
+ Y: float32(rl.GetScreenHeight()),
}
+ base.cache.CalculateOffsets(span.Width, span.Height, *base.Style.Padding, *base.Style.Padding)
+ var weightToScale = getWeightToPixelsRatio(base, base.cache.Width)
+ var spacingPx = base.Spacing * span.Width
+ rl.TraceLog(rl.LogInfo, "Spacing: %v (%v px)", base.Spacing, spacingPx)
+ base.cache.CalculateRowsLocations(base.Objects, weightToScale, spacingPx, span.X)
}
diff --git a/engine/UI/Label.go b/engine/UI/Label.go
index f412eff..e864c85 100644
--- a/engine/UI/Label.go
+++ b/engine/UI/Label.go
@@ -25,6 +25,9 @@ type Label struct {
func (base *Label) Init(*Menu) {
base.Style.FillMissing(defaultLabelStyle)
+ if base.WidthWeight == 0 {
+ base.WidthWeight = 1
+ }
}
func (base *Label) Destroy() {
diff --git a/engine/UI/Menu.go b/engine/UI/Menu.go
index e046a0e..8f9328f 100644
--- a/engine/UI/Menu.go
+++ b/engine/UI/Menu.go
@@ -16,46 +16,11 @@ type Menu struct {
// Spaces between the rows
Spacing float32
// A horizontal line of elements
- Rows []*GridRow
+ Rows []UIElement
cache *layoutCache
}
-// The pixel scalin
-type layoutCache struct {
- // The resolution the cache was calculated for
- ScreenResolution rl.Vector2
- // Horizontal offset in pixels
- OffsetX float32
- // Vertical offset in pixels
- OffsetY float32
- // The Y size of a row
- Width float32
- // The horizontal start and end of each row.
- // Index of an array is representive with row index
- RowLocations []rl.Vector2
-}
-
-func (base *layoutCache) CalculateOffsets(paddingX float32, paddingY float32) {
- base.OffsetX = (base.ScreenResolution.X * paddingX)
- base.OffsetY = (base.ScreenResolution.Y * paddingY)
- base.Width = base.ScreenResolution.X - base.OffsetX * 2
-}
-
-func (base *layoutCache) CalculateRowsLocations (rows []*GridRow, WeightToPixels float32, spacing float32) {
- var spacingPixels = (base.ScreenResolution.Y * spacing)
- base.RowLocations = make([]rl.Vector2, len(rows))
- var y float32 = base.OffsetY
- for i, v := range rows {
- var rowHeight = (WeightToPixels * v.HeightWeight)
- base.RowLocations[i] = rl.Vector2 {
- X: y,
- Y: rowHeight,
- }
- y += rowHeight + spacingPixels
- }
-}
-
func (base *Menu) Create(manager *coreobjects.SceneManager) {
base.manager = manager
base.cache = &layoutCache{}
@@ -81,7 +46,7 @@ func (base *Menu) Draw() {
for i, v := range base.Rows {
var verticalSpacing = base.cache.RowLocations[i]
- v.Draw(rl.Rectangle{
+ v.Draw(&rl.Rectangle{
X: base.cache.OffsetX,
Y: verticalSpacing.X,
Width: base.cache.Width,
@@ -126,9 +91,18 @@ func (base *Menu) generateLayout() {
X: float32(rl.GetScreenWidth()),
Y: float32(rl.GetScreenHeight()),
}
- base.cache.CalculateOffsets(base.PaddingX, base.PaddingY)
+ base.cache.SpanResolution = rl.Vector2{
+ X: float32(rl.GetScreenWidth()),
+ Y: float32(rl.GetScreenHeight()),
+ }
+ base.cache.CalculateOffsets(
+ float32(rl.GetScreenWidth()),
+ float32(rl.GetScreenHeight()),
+ base.PaddingX,
+ base.PaddingY)
var weightToScale = base.getWeightToPixelRatio()
- base.cache.CalculateRowsLocations(base.Rows, weightToScale, base.Spacing)
+ var spacingPx = base.cache.Width * base.Spacing
+ base.cache.CalculateRowsLocations(base.Rows, weightToScale, spacingPx, base.cache.OffsetY)
}
// Sums up all the weights
@@ -136,7 +110,7 @@ func (base *Menu) getWeightToPixelRatio() float32 {
var rowsAmount = len(base.Rows)
var sum float32 = 0
for _, v := range base.Rows {
- sum += v.HeightWeight
+ sum += v.GetOccupationWeight()
}
var spacingPixels = base.cache.ScreenResolution.Y * base.Spacing
var spacing = float32(rowsAmount - 1) * spacingPixels
diff --git a/engine/UI/Style.go b/engine/UI/Style.go
index 091a6a3..1e05bcf 100644
--- a/engine/UI/Style.go
+++ b/engine/UI/Style.go
@@ -29,3 +29,12 @@ func (base *Style) FillMissing(defaultStyle *Style) {
base.Roundness = defaultLabelStyle.Roundness
}
}
+
+// Ensures that the provided style is not nil and fills in gaps with default style
+func InitStyle(provided *Style, defaultStyle *Style) *Style {
+ if provided == nil {
+ return defaultStyle
+ }
+ provided.FillMissing(defaultStyle)
+ return provided
+}
diff --git a/engine/main.go b/engine/main.go
index 0d2e657..ea29794 100644
--- a/engine/main.go
+++ b/engine/main.go
@@ -42,14 +42,17 @@ func menu_test() *ui.Menu {
PaddingX: 0.05,
PaddingY: 0.1,
Spacing: 0.025,
- Rows: []*ui.GridRow {
- {
+ Rows: []ui.UIElement {
+ &ui.GridRow {
HeightWeight: 1,
+ Spacing: 0.01,
Objects: []ui.UIElement {
- &ui.Label{ Text: "Ruines of Rafdolon" },
+ &ui.Label{ Text: "First piece" },
+ &ui.Label{ Text: "Wide piece", WidthWeight: 2 },
+ &ui.Label{ Text: "Another piece" },
},
},
- {
+ &ui.GridRow {
HeightWeight: 2,
Objects: []ui.UIElement {
&ui.Button {
@@ -63,10 +66,10 @@ func menu_test() *ui.Menu {
},
},
},
- {
+ &ui.GridRow {
HeightWeight: 1,
Objects: []ui.UIElement {
- &ui.Label{ Text: "Test text" },
+ &ui.Label{ Text: "A very very long text that is bigger than a window" },
},
},
},