diff --git a/common/elements/v1/block.go b/common/elements/v1/block.go deleted file mode 100644 index 64d9a14..0000000 --- a/common/elements/v1/block.go +++ /dev/null @@ -1,28 +0,0 @@ -package elements - -import ( - "github.com/hajimehoshi/ebiten/v2" -) - -type BlockOption func(*block) - -func Block(ops ...BlockOption) ElementFunc { - return func(d Dimensions) Element { - b := block{} - for i := range ops { - ops[i](&b) - } - return &b - } -} - -type block struct { - width float64 - height float64 - xAlign xAlign - yAlign yAlign -} - -func (b block) Draw(image *ebiten.Image, anchorX, anchorY float64) (w, h float64) { - return b.width, b.height -} diff --git a/common/elements/v1/blocks/block.go b/common/elements/v1/blocks/block.go new file mode 100644 index 0000000..d34f263 --- /dev/null +++ b/common/elements/v1/blocks/block.go @@ -0,0 +1,58 @@ +package blocks + +import ( + "image/color" + + "git.vezzani.net/ben/games/common/elements/v1" + "git.vezzani.net/ben/games/common/elements/v1/mouse" + "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/vector" +) + +func New(ops ...Option) elements.ElementFunc { + return func(d elements.Dimensions) elements.Element { + b := Block{ + InheritedDimensions: d, + } + for i := range ops { + ops[i](&b) + } + return &b + } +} + +type Block struct { + InheritedDimensions elements.Dimensions + backgroundColor *color.Color + mouse.NopHandler + width float64 + height float64 + name string +} + +func (b *Block) Size() (w, h float64) { + w, h = b.InheritedDimensions.WX, b.InheritedDimensions.WY + if b.width != 0 { + w = b.width + } + if b.height != 0 { + h = b.height + } + return +} + +func (b *Block) Draw(image *ebiten.Image) (w, h float64) { + w, h = b.Size() + if b.backgroundColor != nil { + vector.DrawFilledRect( + image, + float32(b.InheritedDimensions.ZX), + float32(b.InheritedDimensions.ZY), + float32(w), + float32(h), + *b.backgroundColor, + true, + ) + } + return +} diff --git a/common/elements/v1/blocks/options.go b/common/elements/v1/blocks/options.go new file mode 100644 index 0000000..352353c --- /dev/null +++ b/common/elements/v1/blocks/options.go @@ -0,0 +1,23 @@ +package blocks + +import "image/color" + +type Option func(*Block) + +func Size(w, h float64) Option { + return func(b *Block) { + b.width, b.height = w, h + } +} + +func BackgroundColor(c color.Color) Option { + return func(b *Block) { + b.backgroundColor = &c + } +} + +func Name(n string) Option { + return func(b *Block) { + b.name = n + } +} diff --git a/common/elements/v1/button.go b/common/elements/v1/button.go index 8a34c96..e59a809 100644 --- a/common/elements/v1/button.go +++ b/common/elements/v1/button.go @@ -1,74 +1,70 @@ package elements -import ( - "context" - "image/color" - - "github.com/hajimehoshi/ebiten/v2" - "github.com/hajimehoshi/ebiten/v2/vector" - "golang.org/x/image/font" -) -import "git.vezzani.net/ben/games/common/ux/v1" - -type xAlign int -type yAlign int - -const ( - AlignCente xAlign = iota - AlignLeft - AlignRight -) - -const ( - AlignCenter yAlign = iota - AlignTop - AlignBottom -) - -type Button struct { - mouseHandler - block - Label string - OnClick func() error - OnRightClick func() error - Style struct { - MouseDownColor *color.Color - } -} - -func (b *Button) HandleClick(_ MouseState) error { - if b.OnClick == nil { - return nil - } - return b.OnClick() -} - -func (b *Button) getFont() font.Face { - if b.block.block.Font == nil { - return ux.FontFace - } - - return *b.block.block.Font -} - -func (b *Button) backgroundColor() color.Color { - var c *color.Color - if b.block.block.BackgroundColor != nil { - c = b.block.block.BackgroundColor - } else { - c = &ux.BackgroundColor - } - - if (b.mouseState.RightDown || b.mouseState.LeftDown) && b.Style.MouseDownColor != nil { - c = b.Style.MouseDownColor - } - - return *c -} - -func (b *Button) Draw(ctx context.Context, image *ebiten.Image) error { - - vector.StrokeRect(image, xz, yz, w, h, 1, b.backgroundColor(), true) - - return nil -} +// +//import ( +// "image/color" +//) +// +//type xAlign int +//type yAlign int +// +//const ( +// AlignCente xAlign = iota +// AlignLeft +// AlignRight +//) +// +//const ( +// AlignCenter yAlign = iota +// AlignTop +// AlignBottom +//) +// +//type Button struct { +// mouseHandler +// block +// Label string +// OnClick func() error +// OnRightClick func() error +// Style struct { +// MouseDownColor *color.Color +// } +//} +// +//func (b *Button) HandleClick(_ MouseState) error { +// if b.OnClick == nil { +// return nil +// } +// return b.OnClick() +//} +// +// +//func (b *Button) getFont() font.Face { +// if b.block.Font == nil { +// return ux.FontFace +// } +// +// return *b.block.block.Font +//} +// +//func (b *Button) backgroundColor() color.Color { +// var c *color.Color +// if b.block.block.BackgroundColor != nil { +// c = b.block.block.BackgroundColor +// } else { +// c = &ux.BackgroundColor +// } +// +// if (b.mouseState.RightDown || b.mouseState.LeftDown) && b.Style.MouseDownColor != nil { +// c = b.Style.MouseDownColor +// } +// +// return *c +//} +// +//func (b *Button) Draw(ctx context.Context, image *ebiten.Image) error { +// +// vector.StrokeRect(image, xz, yz, w, h, 1, b.backgroundColor(), true) +// +// return nil +//} diff --git a/common/elements/v1/element.go b/common/elements/v1/element.go index 8e28b6f..86b7d5f 100644 --- a/common/elements/v1/element.go +++ b/common/elements/v1/element.go @@ -25,44 +25,12 @@ type Mouseable interface { } type Element interface { - Draw(image *ebiten.Image, anchorX, anchorY float64) (w, h float64) + Mouseable + Clickable + Draw(image *ebiten.Image) (w, h float64) } type Dimensions struct { - zx, zy float64 - wx, wy float64 -} - -type mouseHandler struct { - mouseState MouseState - prevMouseState MouseState -} - -func (b *mouseHandler) HandleMouseEnter(s MouseState) error { - b.mouseState = s - return nil -} - -func (b *mouseHandler) HandleMouseLeave(s MouseState) error { - b.prevMouseState = b.mouseState - b.mouseState = MouseState{} - return nil -} - -func (b *mouseHandler) HandleMouseMove(s MouseState) error { - b.prevMouseState = b.mouseState - b.mouseState = s - return nil -} - -func (b *mouseHandler) HandleMouseDown(s MouseState) error { - b.prevMouseState = b.mouseState - b.mouseState = s - return nil -} - -func (b *mouseHandler) HandleMouseUp(s MouseState) error { - b.prevMouseState = b.mouseState - b.mouseState = s - return nil + ZX, ZY float64 + WX, WY float64 } diff --git a/common/elements/v1/mouse/mouse.go b/common/elements/v1/mouse/mouse.go new file mode 100644 index 0000000..e53e766 --- /dev/null +++ b/common/elements/v1/mouse/mouse.go @@ -0,0 +1,29 @@ +package mouse + +import "git.vezzani.net/ben/games/common/elements/v1" + +type NopHandler struct{} + +func (n NopHandler) HandleClick(s elements.MouseState) error { + return nil +} + +func (n NopHandler) HandleMouseEnter(s elements.MouseState) error { + return nil +} + +func (n NopHandler) HandleMouseLeave(s elements.MouseState) error { + return nil +} + +func (n NopHandler) HandleMouseMove(s elements.MouseState) error { + return nil +} + +func (n NopHandler) HandleMouseDown(s elements.MouseState) error { + return nil +} + +func (n NopHandler) HandleMouseUp(s elements.MouseState) error { + return nil +} diff --git a/common/elements/v1/stack.go b/common/elements/v1/stack.go deleted file mode 100644 index c7450eb..0000000 --- a/common/elements/v1/stack.go +++ /dev/null @@ -1,31 +0,0 @@ -package elements - -import "github.com/hajimehoshi/ebiten/v2" - -type StackOption func(*stack) - -func Stack(ops ...StackOption) ElementFunc { - return func(parentDimensions Dimensions) Element { - - } -} - -type stack struct { - block - horizontal bool - children []Element -} - -func (s *stack) Draw(image *ebiten.Image, anchorX, anchorY float64) (w, h float64) { - var offsetX, offsetY float64 - originalX, originalY := anchorX, anchorY - for i := range s.children { - offsetX, offsetY = s.children[i].Draw(image, anchorX, anchorY) - if s.horizontal { - anchorX += offsetX - } else { - anchorY += offsetY - } - } - return anchorX - originalX, anchorY - originalY -} diff --git a/common/elements/v1/stacks/options.go b/common/elements/v1/stacks/options.go new file mode 100644 index 0000000..8ed006b --- /dev/null +++ b/common/elements/v1/stacks/options.go @@ -0,0 +1,26 @@ +package stacks + +import ( + "git.vezzani.net/ben/games/common/elements/v1" + "git.vezzani.net/ben/games/common/elements/v1/blocks" +) + +type Option func(*Stack) + +func BlockOpt(o blocks.Option) Option { + return func(s *Stack) { + o(&s.Block) + } +} + +func Children(children ...elements.ElementFunc) Option { + return func(s *Stack) { + s.children = children + } +} + +func Horizontal() Option { + return func(s *Stack) { + s.horizontal = true + } +} diff --git a/common/elements/v1/stacks/stack.go b/common/elements/v1/stacks/stack.go new file mode 100644 index 0000000..bcb1522 --- /dev/null +++ b/common/elements/v1/stacks/stack.go @@ -0,0 +1,51 @@ +package stacks + +import ( + "git.vezzani.net/ben/games/common/elements/v1" + "git.vezzani.net/ben/games/common/elements/v1/blocks" + "git.vezzani.net/ben/games/common/elements/v1/mouse" + + "github.com/hajimehoshi/ebiten/v2" +) + +func New(ops ...Option) elements.ElementFunc { + return func(d elements.Dimensions) elements.Element { + s := Stack{ + Block: blocks.Block{InheritedDimensions: d}, + } + for op := range ops { + ops[op](&s) + } + return &s + } +} + +type Stack struct { + blocks.Block + mouse.NopHandler + horizontal bool + children []elements.ElementFunc +} + +func (s *Stack) Draw(image *ebiten.Image) (w, h float64) { + s.Block.Draw(image) + + d := s.InheritedDimensions + d.WX, d.WY = s.Block.Size() + if s.horizontal { + d.WX = d.WX / float64(len(s.children)) + } else { + d.WY = d.WY / float64(len(s.children)) + } + + var offsetX, offsetY float64 + for i := range s.children { + offsetX, offsetY = s.children[i](d).Draw(image) + if s.horizontal { + d.ZX += offsetX + } else { + d.ZY += offsetY + } + } + return s.Block.Size() +} diff --git a/common/elements/v1/table.go b/common/elements/v1/table.go index e546916..49509d0 100644 --- a/common/elements/v1/table.go +++ b/common/elements/v1/table.go @@ -1,92 +1,93 @@ package elements -import ( - "context" - "fmt" - - "github.com/hajimehoshi/ebiten/v2" -) - -type Table struct { - mouseHandler - block - - ColumnCount int - RowCount int - - Cells []Dimensions - - Style struct { - } - - mouseOverCell int -} - -func (t *Table) HandleClick(ctx context.Context, s MouseState) error { - address := t.getAddressUnderMouse() - if address < 0 || address >= len(t.Cells) { - return fmt.Errorf("cell address under mouse is out of bounds") - } - - if clickable, ok := t.Cells[address].(Clickable); ok { - return clickable.HandleClick(s) - } - - return nil -} - -func (t *Table) HandleMouseEnter(ctx context.Context, s MouseState) error { - _ = t.mouseHandler.HandleMouseEnter(s) - address := t.getAddressUnderMouse() - if address < 0 || address >= len(t.Cells) { - return fmt.Errorf("cell address under mouse is out of bounds") - } - - if mouseable, ok := t.Cells[address].(Mouseable); ok { - s.X -= - return mouseable.HandleMouseEnter(s) - } - - return nil -} - -func (t *Table) HandleMouseLeave(ctx context.Context, s MouseState) error { - _ = t.mouseHandler.HandleMouseLeave(s) - return nil -} - -func (t *Table) HandleMouseMove(ctx context.Context, s MouseState) error { - _ = t.mouseHandler.HandleMouseMove(s) - return nil -} - -func (t *Table) HandleMouseDown(ctx context.Context, s MouseState) error { - _ = t.mouseHandler.HandleMouseDown(s) - return nil -} - -func (t *Table) HandleMouseUp(ctx context.Context, s MouseState) error { - _ = t.mouseHandler.HandleMouseUp(s) - return nil -} - -func (t *Table) CellSize() (w, h float32) { - w, h = t. - return w / float32(t.ColumnCount), h / float32(t.RowCount) -} - -func (t *Table) CellZero(ctx context.Context, addr int) (x, y float32) { - x, y = GetZero(ctx) - w, h := t.CellSize(ctx) - - col, row := addr%t.ColumnCount, addr/t.ColumnCount - return x + float32(col)*w, y + float32(row) + h -} - -func (t *Table) Draw(screen *ebiten.Image, zx, zy float64) error { - return nil -} - -func (t *Table) getAddressUnderMouse() int { - return int(t.mouseState.Y)*t.RowCount + int(t.mouseState.X) -} +// +//import ( +// "context" +// "fmt" +// +// "github.com/hajimehoshi/ebiten/v2" +//) +// +//type Table struct { +// mouseHandler +// block +// +// ColumnCount int +// RowCount int +// +// Cells []Dimensions +// +// Style struct { +// } +// +// mouseOverCell int +//} +// +//func (t *Table) HandleClick(ctx context.Context, s MouseState) error { +// address := t.getAddressUnderMouse() +// if address < 0 || address >= len(t.Cells) { +// return fmt.Errorf("cell address under mouse is out of bounds") +// } +// +// if clickable, ok := t.Cells[address].(Clickable); ok { +// return clickable.HandleClick(s) +// } +// +// return nil +//} +// +//func (t *Table) HandleMouseEnter(ctx context.Context, s MouseState) error { +// _ = t.mouseHandler.HandleMouseEnter(s) +// address := t.getAddressUnderMouse() +// if address < 0 || address >= len(t.Cells) { +// return fmt.Errorf("cell address under mouse is out of bounds") +// } +// +// if mouseable, ok := t.Cells[address].(Mouseable); ok { +// s.X -= +// return mouseable.HandleMouseEnter(s) +// } +// +// return nil +//} +// +//func (t *Table) HandleMouseLeave(ctx context.Context, s MouseState) error { +// _ = t.mouseHandler.HandleMouseLeave(s) +// return nil +//} +// +//func (t *Table) HandleMouseMove(ctx context.Context, s MouseState) error { +// _ = t.mouseHandler.HandleMouseMove(s) +// return nil +//} +// +//func (t *Table) HandleMouseDown(ctx context.Context, s MouseState) error { +// _ = t.mouseHandler.HandleMouseDown(s) +// return nil +//} +// +//func (t *Table) HandleMouseUp(ctx context.Context, s MouseState) error { +// _ = t.mouseHandler.HandleMouseUp(s) +// return nil +//} +// +//func (t *Table) CellSize() (w, h float32) { +// w, h = t. +// return w / float32(t.ColumnCount), h / float32(t.RowCount) +//} +// +//func (t *Table) CellZero(ctx context.Context, addr int) (x, y float32) { +// x, y = GetZero(ctx) +// w, h := t.CellSize(ctx) +// +// col, row := addr%t.ColumnCount, addr/t.ColumnCount +// return x + float32(col)*w, y + float32(row) + h +//} +// +//func (t *Table) Draw(screen *ebiten.Image, zx, zy float64) error { +// return nil +//} +// +//func (t *Table) getAddressUnderMouse() int { +// return int(t.mouseState.Y)*t.RowCount + int(t.mouseState.X) +//} diff --git a/tools/component_test/editor.go b/tools/component_test/editor.go new file mode 100644 index 0000000..ed06cdb --- /dev/null +++ b/tools/component_test/editor.go @@ -0,0 +1,62 @@ +package main + +import ( + "image/color" + + "git.vezzani.net/ben/games/common/elements/v1" + "git.vezzani.net/ben/games/common/elements/v1/blocks" + "git.vezzani.net/ben/games/common/elements/v1/stacks" + "git.vezzani.net/ben/games/common/sprites/v1" + "github.com/hajimehoshi/ebiten/v2" + "golang.org/x/image/colornames" +) + +var menu = stacks.New( + stacks.Horizontal(), + stacks.BlockOpt(blocks.BackgroundColor(color.White)), + stacks.BlockOpt(blocks.Size(200, 200)), + stacks.BlockOpt(blocks.Name("parent")), + stacks.Children( + stacks.New( + stacks.BlockOpt(blocks.Name("left")), + stacks.Children( + blocks.New(blocks.BackgroundColor(colornames.Green)), + blocks.New(blocks.BackgroundColor(colornames.Yellow)), + )), + stacks.New( + stacks.BlockOpt(blocks.Name("right")), + stacks.Children( + blocks.New(blocks.BackgroundColor(colornames.Blue)), + blocks.New(blocks.BackgroundColor(colornames.Red)), + ), + ), + ), +) + +func newEditor() *editor { + return &editor{} +} + +type editor struct { +} + +func (e *editor) Update() error { + sprites.Update() + + return nil +} + +func (e *editor) Draw(screen *ebiten.Image) { + b := screen.Bounds() + menu(elements.Dimensions{ + ZX: float64(b.Min.X), + ZY: float64(b.Min.Y), + WX: float64(b.Max.X), + WY: float64(b.Max.Y), + }).Draw(screen) + //panic("done") +} + +func (e *editor) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { + return outsideWidth, outsideHeight +} diff --git a/tools/component_test/main.go b/tools/component_test/main.go new file mode 100644 index 0000000..a7d70bb --- /dev/null +++ b/tools/component_test/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "github.com/hajimehoshi/ebiten/v2" +) + +func main() { + ebiten.SetWindowSize(480, 320) + ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) + ebiten.SetWindowTitle("Component/Layout Test") + e := newEditor() + if err := ebiten.RunGame(e); err != nil { + panic(err) + } +} diff --git a/tools/spritedit/editor.go b/tools/spritedit/editor.go index 7f88726..fc02121 100644 --- a/tools/spritedit/editor.go +++ b/tools/spritedit/editor.go @@ -1,21 +1,48 @@ package main -import "github.com/hajimehoshi/ebiten/v2" +import ( + "image/color" + + "git.vezzani.net/ben/games/common/elements/v1" + "git.vezzani.net/ben/games/common/elements/v1/blocks" + "git.vezzani.net/ben/games/common/elements/v1/stacks" + "git.vezzani.net/ben/games/common/sprites/v1" + "github.com/hajimehoshi/ebiten/v2" + "golang.org/x/image/colornames" +) + +var menu = stacks.New( + stacks.BlockOpt(blocks.BackgroundColor(color.White)), + stacks.BlockOpt(blocks.Size(100, 200)), + stacks.Children( + blocks.New(blocks.BackgroundColor(colornames.Green)), + blocks.New(), + ), +) + +func newEditor() *editor { + return &editor{} +} type editor struct { } func (e *editor) Update() error { - //TODO implement me - panic("implement me") + sprites.Update() + + return nil } func (e *editor) Draw(screen *ebiten.Image) { - //TODO implement me - panic("implement me") + b := screen.Bounds() + menu(elements.Dimensions{ + ZX: float64(b.Min.X), + ZY: float64(b.Min.Y), + WX: float64(b.Max.X), + WY: float64(b.Max.Y), + }).Draw(screen) } func (e *editor) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { - //TODO implement me - panic("implement me") + return outsideWidth, outsideHeight } diff --git a/tools/spritedit/main.go b/tools/spritedit/main.go index 16c432c..530162d 100644 --- a/tools/spritedit/main.go +++ b/tools/spritedit/main.go @@ -1,15 +1,15 @@ package main import ( - "bytes" - "github.com/hajimehoshi/ebiten/v2" ) func main() { ebiten.SetWindowSize(480, 320) ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) - if err := ebiten.RunGame(); err != nil { + ebiten.SetWindowTitle("Sprite Editor") + e := newEditor() + if err := ebiten.RunGame(e); err != nil { panic(err) } }