From 881d5f1f71988a7a46bf04bfc310db699934398f Mon Sep 17 00:00:00 2001 From: juander Date: Fri, 6 Nov 2020 12:38:20 +0100 Subject: [PATCH] d2ui: Create default base widget this encapsulates all the repeating functions defined for all widgets in the same way, like Set/GetPosition(). --- d2core/d2ui/button.go | 49 +++------------------ d2core/d2ui/checkbox.go | 44 ++----------------- d2core/d2ui/drawable.go | 1 + d2core/d2ui/frame.go | 17 ++++---- d2core/d2ui/label.go | 26 ++++------- d2core/d2ui/scrollbar.go | 39 +++-------------- d2core/d2ui/sprite.go | 21 ++++----- d2core/d2ui/textbox.go | 39 ++++------------- d2core/d2ui/tooltip.go | 14 ++---- d2core/d2ui/widget.go | 57 +++++++++++++++++++++++++ d2game/d2gamescreen/character_select.go | 5 ++- d2game/d2gamescreen/credits.go | 7 ++- 12 files changed, 121 insertions(+), 198 deletions(-) diff --git a/d2core/d2ui/button.go b/d2core/d2ui/button.go index 9389fd7a..b9a647ba 100644 --- a/d2core/d2ui/button.go +++ b/d2core/d2ui/button.go @@ -242,32 +242,28 @@ var _ Widget = &Button{} // static check to ensure button implements widget // Button defines a standard wide UI button type Button struct { - manager *UIManager + *BaseWidget buttonLayout ButtonLayout normalSurface d2interface.Surface pressedSurface d2interface.Surface toggledSurface d2interface.Surface pressedToggledSurface d2interface.Surface disabledSurface d2interface.Surface - x int - y int - width int - height int onClick func() enabled bool - visible bool pressed bool toggled bool } // NewButton creates an instance of Button func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button { + base := NewBaseWidget(ui) + base.SetVisible(true) + btn := &Button{ - width: 0, - height: 0, - visible: true, - enabled: true, - pressed: false, + BaseWidget: base, + enabled: true, + pressed: false, } buttonLayout := getButtonLayouts()[buttonType] @@ -426,11 +422,6 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab } } -// bindManager binds the button to the UI manager -func (v *Button) bindManager(manager *UIManager) { - v.manager = manager -} - // OnActivated defines the callback handler for the activate event func (v *Button) OnActivated(callback func()) { v.onClick = callback @@ -495,32 +486,6 @@ func (v *Button) SetEnabled(enabled bool) { v.enabled = enabled } -// GetSize returns the size of the button -func (v *Button) GetSize() (width, height int) { - return v.width, v.height -} - -// SetPosition moves the button -func (v *Button) SetPosition(x, y int) { - v.x = x - v.y = y -} - -// GetPosition returns the location of the button -func (v *Button) GetPosition() (x, y int) { - return v.x, v.y -} - -// GetVisible returns the visibility of the button -func (v *Button) GetVisible() bool { - return v.visible -} - -// SetVisible sets the visibility of the button -func (v *Button) SetVisible(visible bool) { - v.visible = visible -} - // GetPressed returns the pressed state of the button func (v *Button) GetPressed() bool { return v.pressed diff --git a/d2core/d2ui/checkbox.go b/d2core/d2ui/checkbox.go index 21daa0c8..f2617fc2 100644 --- a/d2core/d2ui/checkbox.go +++ b/d2core/d2ui/checkbox.go @@ -10,16 +10,11 @@ import ( // Checkbox represents a checkbox UI element type Checkbox struct { - manager *UIManager + *BaseWidget Image d2interface.Surface checkedImage d2interface.Surface - x int - y int - width int - height int onClick func() checkState bool - visible bool enabled bool } @@ -27,11 +22,11 @@ type Checkbox struct { func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox { var err error + base := NewBaseWidget(ui) + result := &Checkbox{ + BaseWidget: base, checkState: checkState, - visible: true, - width: 0, - height: 0, enabled: true, } @@ -70,11 +65,6 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox { return result } -// bindManager binds the checkbox to the UI manager -func (v *Checkbox) bindManager(manager *UIManager) { - v.manager = manager -} - // Render renders the checkbox func (v *Checkbox) Render(target d2interface.Surface) error { target.PushTranslation(v.x, v.y) @@ -140,29 +130,3 @@ func (v *Checkbox) Activate() { v.onClick() } - -// GetPosition returns the position of the checkbox -func (v *Checkbox) GetPosition() (x, y int) { - return v.x, v.y -} - -// GetSize returns the size of the checkbox -func (v *Checkbox) GetSize() (width, height int) { - return v.width, v.height -} - -// GetVisible returns the visibility state of the checkbox -func (v *Checkbox) GetVisible() bool { - return v.visible -} - -// SetPosition sets the position of the checkbox -func (v *Checkbox) SetPosition(x, y int) { - v.x = x - v.y = y -} - -// SetVisible sets the visibility of the checkbox -func (v *Checkbox) SetVisible(visible bool) { - v.visible = visible -} diff --git a/d2core/d2ui/drawable.go b/d2core/d2ui/drawable.go index 09e0852d..277525b0 100644 --- a/d2core/d2ui/drawable.go +++ b/d2core/d2ui/drawable.go @@ -11,6 +11,7 @@ type Drawable interface { GetSize() (width, height int) SetPosition(x, y int) GetPosition() (x, y int) + OffsetPosition(xo, yo int) GetVisible() bool SetVisible(visible bool) } diff --git a/d2core/d2ui/frame.go b/d2core/d2ui/frame.go index 54275737..f5d7c828 100644 --- a/d2core/d2ui/frame.go +++ b/d2core/d2ui/frame.go @@ -19,11 +19,9 @@ const ( // UIFrame is a representation of a ui panel that occupies the left or right half of the screen // when it is visible. type UIFrame struct { + *BaseWidget asset *d2asset.AssetManager - uiManager *UIManager frame *Sprite - originX int - originY int frameOrientation frameOrientation } @@ -58,12 +56,13 @@ func NewUIFrame( originY = 0 } + base := NewBaseWidget(uiManager) + base.SetPosition(originX, originY) + frame := &UIFrame{ + BaseWidget: base, asset: asset, - uiManager: uiManager, frameOrientation: frameOrientation, - originX: originX, - originY: originY, } frame.Load() @@ -72,7 +71,7 @@ func NewUIFrame( // Load the necessary frame resources func (u *UIFrame) Load() { - sprite, err := u.uiManager.NewSprite(d2resource.Frame, d2resource.PaletteSky) + sprite, err := u.manager.NewSprite(d2resource.Frame, d2resource.PaletteSky) if err != nil { log.Print(err) } @@ -105,7 +104,7 @@ func (u *UIFrame) renderLeft(target d2interface.Surface) error { // the frame coordinates coord := make(map[int]*struct{ x, y int }) - startX, startY := u.originX, u.originY + startX, startY := u.GetPosition() currentX, currentY := startX, startY // first determine the coordinates for each frame @@ -162,7 +161,7 @@ func (u *UIFrame) renderRight(target d2interface.Surface) error { // the frame coordinates coord := make(map[int]*struct{ x, y int }) - startX, startY := u.originX, u.originY + startX, startY := u.GetPosition() currentX, currentY := startX, startY // first determine the coordinates for each frame diff --git a/d2core/d2ui/label.go b/d2core/d2ui/label.go index cb16a6db..3fa4db4f 100644 --- a/d2core/d2ui/label.go +++ b/d2core/d2ui/label.go @@ -15,10 +15,8 @@ import ( // Label represents a user interface label type Label struct { - manager *UIManager + *BaseWidget text string - X int - Y int Alignment d2gui.HorizontalAlign font *d2asset.Font Color map[int]color.Color @@ -33,10 +31,13 @@ func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label { return nil } + base := NewBaseWidget(ui) + result := &Label{ - Alignment: d2gui.HorizontalAlignLeft, - Color: map[int]color.Color{0: color.White}, - font: font, + BaseWidget: base, + Alignment: d2gui.HorizontalAlignLeft, + Color: map[int]color.Color{0: color.White}, + font: font, } result.bindManager(ui) @@ -46,7 +47,7 @@ func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label { // Render draws the label on the screen, respliting the lines to allow for other alignments. func (v *Label) Render(target d2interface.Surface) { - target.PushTranslation(v.X, v.Y) + target.PushTranslation(v.GetPosition()) lines := strings.Split(v.text, "\n") yOffset := 0 @@ -91,17 +92,6 @@ func (v *Label) Render(target d2interface.Surface) { target.Pop() } -// bindManager binds the label to the UI manager -func (v *Label) bindManager(manager *UIManager) { - v.manager = manager -} - -// SetPosition moves the label to the specified location -func (v *Label) SetPosition(x, y int) { - v.X = x - v.Y = y -} - // GetSize returns the size of the label func (v *Label) GetSize() (width, height int) { return v.font.GetTextMetrics(v.text) diff --git a/d2core/d2ui/scrollbar.go b/d2core/d2ui/scrollbar.go index 7354ea6b..399f09ab 100644 --- a/d2core/d2ui/scrollbar.go +++ b/d2core/d2ui/scrollbar.go @@ -17,9 +17,7 @@ const ( // Scrollbar is a vertical slider ui element type Scrollbar struct { - manager *UIManager - x, y, height int - visible bool + *BaseWidget enabled bool currentOffset int maxOffset int @@ -36,12 +34,13 @@ func (ui *UIManager) NewScrollbar(x, y, height int) *Scrollbar { return nil } + base := NewBaseWidget(ui) + base.SetPosition(x, y) + base.height = height + result := &Scrollbar{ - visible: true, + BaseWidget: base, enabled: true, - x: x, - y: y, - height: height, scrollbarSprite: scrollbarSprite, } @@ -146,11 +145,6 @@ func (v *Scrollbar) Render(target d2interface.Surface) error { return nil } -// bindManager binds the scrollbar to the UI manager -func (v *Scrollbar) bindManager(manager *UIManager) { - v.manager = manager -} - // Advance advances the scrollbar sprite func (v *Scrollbar) Advance(elapsed float64) error { return v.scrollbarSprite.Advance(elapsed) @@ -161,27 +155,6 @@ func (v *Scrollbar) GetSize() (width, height int) { return scrollbarWidth, v.height } -// SetPosition sets the scrollbar x,y position -func (v *Scrollbar) SetPosition(x, y int) { - v.x = x - v.y = y -} - -// GetPosition returns the scrollbar x,y position -func (v *Scrollbar) GetPosition() (x, y int) { - return v.x, v.y -} - -// GetVisible returns whether or not the scrollbar is visible -func (v *Scrollbar) GetVisible() bool { - return v.visible -} - -// SetVisible sets the scrollbar visibility state -func (v *Scrollbar) SetVisible(visible bool) { - v.visible = visible -} - // SetMaxOffset sets the maximum offset of the scrollbar func (v *Scrollbar) SetMaxOffset(maxOffset int) { v.maxOffset = maxOffset diff --git a/d2core/d2ui/sprite.go b/d2core/d2ui/sprite.go index e1cc4f74..fd28bafb 100644 --- a/d2core/d2ui/sprite.go +++ b/d2core/d2ui/sprite.go @@ -13,8 +13,7 @@ import ( // Sprite is a positioned visual object. type Sprite struct { - x int - y int + *BaseWidget animation d2interface.Animation } @@ -31,7 +30,11 @@ func (ui *UIManager) NewSprite(animationPath, palettePath string) (*Sprite, erro animation.BindRenderer(ui.renderer) - return &Sprite{animation: animation}, nil + base := NewBaseWidget(ui) + + return &Sprite{ + BaseWidget: base, + animation: animation}, nil } // Render renders the sprite on the given surface @@ -80,15 +83,9 @@ func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segments return nil } -// SetPosition places the sprite in 2D -func (s *Sprite) SetPosition(x, y int) { - s.x = x - s.y = y -} - -// GetPosition retrieves the 2D position of the sprite -func (s *Sprite) GetPosition() (x, y int) { - return s.x, s.y +// GetSize returns the size of the current frame +func (s *Sprite) GetSize() (width, height int) { + return s.GetCurrentFrameSize() } // GetFrameSize gets the Size(width, height) of a indexed frame. diff --git a/d2core/d2ui/textbox.go b/d2core/d2ui/textbox.go index 588effdd..0d104af5 100644 --- a/d2core/d2ui/textbox.go +++ b/d2core/d2ui/textbox.go @@ -12,15 +12,12 @@ import ( // TextBox represents a text input box type TextBox struct { - manager *UIManager + *BaseWidget textLabel *Label lineBar *Label text string filter string - x int - y int bgSprite *Sprite - visible bool enabled bool isFocused bool } @@ -33,13 +30,15 @@ func (ui *UIManager) NewTextbox() *TextBox { return nil } + base := NewBaseWidget(ui) + tb := &TextBox{ - filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", - bgSprite: bgSprite, - textLabel: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits), - lineBar: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits), - enabled: true, - visible: true, + BaseWidget: base, + filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + bgSprite: bgSprite, + textLabel: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits), + lineBar: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits), + enabled: true, } tb.lineBar.SetText("_") @@ -69,11 +68,6 @@ func (v *TextBox) Render(target d2interface.Surface) error { return nil } -// bindManager binds the textbox to the UI manager -func (v *TextBox) bindManager(manager *UIManager) { - v.manager = manager -} - // OnKeyChars handles key character events func (v *TextBox) OnKeyChars(event d2interface.KeyCharsEvent) bool { if !v.isFocused || !v.visible || !v.enabled { @@ -189,21 +183,6 @@ func (v *TextBox) SetPosition(x, y int) { v.bgSprite.SetPosition(v.x, v.y+26) } -// GetPosition returns the position of the text box -func (v *TextBox) GetPosition() (x, y int) { - return v.x, v.y -} - -// GetVisible returns the visibility of the text box -func (v *TextBox) GetVisible() bool { - return v.visible -} - -// SetVisible sets the visibility of the text box -func (v *TextBox) SetVisible(visible bool) { - v.visible = visible -} - // GetEnabled returns the enabled state of the text box func (v *TextBox) GetEnabled() bool { return v.enabled diff --git a/d2core/d2ui/tooltip.go b/d2core/d2ui/tooltip.go index af3489ae..6f514645 100644 --- a/d2core/d2ui/tooltip.go +++ b/d2core/d2ui/tooltip.go @@ -16,11 +16,10 @@ const ( // Tooltip contains a label containing text with a transparent, black background type Tooltip struct { - manager *UIManager + *BaseWidget lines []string label *Label backgroundColor int - x, y int originX tooltipXOrigin originY tooltipYOrigin boxEnabled bool @@ -56,11 +55,12 @@ func (ui *UIManager) NewTooltip(font, label := ui.NewLabel(font, palette) label.Alignment = d2gui.HorizontalAlignCenter + base := NewBaseWidget(ui) + res := &Tooltip{ + BaseWidget: base, backgroundColor: blackAlpha70, label: label, - x: 0, - y: 0, originX: originX, originY: originY, boxEnabled: true, @@ -70,12 +70,6 @@ func (ui *UIManager) NewTooltip(font, return res } -// SetPosition sets the position of the origin point of the tooltip -func (t *Tooltip) SetPosition(x, y int) { - t.x = x - t.y = y -} - // SetTextLines sets the tooltip text in the form of an array of strings func (t *Tooltip) SetTextLines(lines []string) { t.lines = lines diff --git a/d2core/d2ui/widget.go b/d2core/d2ui/widget.go index f2ac7ea6..5466583a 100644 --- a/d2core/d2ui/widget.go +++ b/d2core/d2ui/widget.go @@ -16,3 +16,60 @@ type ClickableWidget interface { OnActivated(callback func()) Activate() } + +// BaseWidget contains default functionality that all widgets share +type BaseWidget struct { + manager *UIManager + x int + y int + width int + height int + visible bool +} + +// NewBaseWidget creates a new BaseWidget with defaults +func NewBaseWidget(manager *UIManager) *BaseWidget { + return &BaseWidget{ + manager: manager, + x: 0, + y: 0, + width: 0, + height: 0, + visible: true, + } +} + +func (b *BaseWidget) bindManager(manager *UIManager) { + b.manager = manager +} + +// GetSize returns the size of the widget +func (b *BaseWidget) GetSize() (width, height int) { + return b.width, b.height +} + +// SetPosition sets the position of the widget +func (b *BaseWidget) SetPosition(x, y int) { + b.x, b.y = x, y +} + +// OffsetPosition moves the widget by x and y +func (b *BaseWidget) OffsetPosition(x, y int) { + b.x += x + b.y += y +} + +// GetPosition returns the position of the widget +func (b *BaseWidget) GetPosition() (x, y int) { + return b.x, b.y +} + +// GetVisible returns whether the widget is visible +func (b *BaseWidget) GetVisible() (visible bool) { + return b.visible +} + +// SetVisible make the widget visible, not visible +func (b *BaseWidget) SetVisible(visible bool) { + b.visible = visible +} diff --git a/d2game/d2gamescreen/character_select.go b/d2game/d2gamescreen/character_select.go index 160880a4..76b74b65 100644 --- a/d2game/d2gamescreen/character_select.go +++ b/d2game/d2gamescreen/character_select.go @@ -392,8 +392,9 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) { v.characterStatsLabel[i].Render(screen) v.characterExpLabel[i].Render(screen) - charImgX := v.characterNameLabel[i].X - selectionBoxImageOffsetX - charImgY := v.characterNameLabel[i].Y + selectionBoxImageOffsetY + x, y := v.characterNameLabel[i].GetPosition() + charImgX := x - selectionBoxImageOffsetX + charImgY := y + selectionBoxImageOffsetY screen.PushTranslation(charImgX, charImgY) v.characterImage[i].Render(screen) screen.Pop() diff --git a/d2game/d2gamescreen/credits.go b/d2game/d2gamescreen/credits.go index fa3afbde..3664883a 100644 --- a/d2game/d2gamescreen/credits.go +++ b/d2game/d2gamescreen/credits.go @@ -159,11 +159,14 @@ func (v *Credits) Advance(tickTime float64) error { continue } - if label.Label.Y-1 < -15 { + _, y := label.Label.GetPosition() + + if y-1 < -15 { label.Available = true continue } - label.Label.Y-- + + label.Label.OffsetPosition(0, -1) } }