...

Source file src/code.rocket9labs.com/tslocum/etk/sprite.go

Documentation: code.rocket9labs.com/tslocum/etk

     1  package etk
     2  
     3  import (
     4  	"image"
     5  
     6  	"github.com/hajimehoshi/ebiten/v2"
     7  )
     8  
     9  // Sprite is a resizable image.
    10  type Sprite struct {
    11  	*Box
    12  
    13  	img       *ebiten.Image
    14  	imgBounds image.Rectangle
    15  
    16  	thumb       *ebiten.Image
    17  	thumbBounds image.Rectangle
    18  
    19  	horizontal Alignment
    20  	vertical   Alignment
    21  }
    22  
    23  // NewSprite returns a new Sprite widget.
    24  func NewSprite(img *ebiten.Image) *Sprite {
    25  	return &Sprite{
    26  		Box:        NewBox(),
    27  		img:        img,
    28  		imgBounds:  img.Bounds(),
    29  		horizontal: AlignCenter,
    30  		vertical:   AlignCenter,
    31  	}
    32  }
    33  
    34  // SetImage sets the image of the Sprite.
    35  func (s *Sprite) SetImage(img *ebiten.Image) {
    36  	s.Lock()
    37  	defer s.Unlock()
    38  
    39  	s.img = img
    40  	s.thumbBounds = image.Rectangle{}
    41  }
    42  
    43  // SetHorizontal sets the horizontal alignment of the Sprite.
    44  func (s *Sprite) SetHorizontal(h Alignment) {
    45  	s.Lock()
    46  	defer s.Unlock()
    47  
    48  	s.horizontal = h
    49  	s.thumbBounds = image.Rectangle{}
    50  }
    51  
    52  // SetVertical sets the vertical alignment of the Sprite.
    53  func (s *Sprite) SetVertical(v Alignment) {
    54  	s.Lock()
    55  	defer s.Unlock()
    56  
    57  	s.vertical = v
    58  	s.thumbBounds = image.Rectangle{}
    59  }
    60  
    61  // Draw draws the Sprite on the screen.
    62  func (s *Sprite) Draw(screen *ebiten.Image) error {
    63  	s.Lock()
    64  	defer s.Unlock()
    65  
    66  	op := &ebiten.DrawImageOptions{}
    67  	op.GeoM.Translate(float64(s.rect.Min.X), float64(s.rect.Min.Y))
    68  	if s.imgBounds.Dx() == s.rect.Dx() && s.imgBounds.Dy() == s.rect.Dy() {
    69  		screen.DrawImage(s.img, op)
    70  		return nil
    71  	} else if s.thumbBounds.Dx() != s.rect.Dx() || s.thumbBounds.Dy() != s.rect.Dy() {
    72  		scale, yScale := float64(s.rect.Dx())/float64(s.imgBounds.Dx()), float64(s.rect.Dy())/float64(s.imgBounds.Dy())
    73  		if yScale < scale {
    74  			scale = yScale
    75  		}
    76  		thumbOp := &ebiten.DrawImageOptions{}
    77  		thumbOp.GeoM.Scale(scale, scale)
    78  		if s.horizontal != AlignStart {
    79  			delta := float64(s.rect.Dx()) - float64(s.imgBounds.Dx())*scale
    80  			if s.horizontal == AlignCenter {
    81  				thumbOp.GeoM.Translate(delta/2, 0)
    82  			} else { // AlignEnd
    83  				thumbOp.GeoM.Translate(delta, 0)
    84  			}
    85  		}
    86  		if s.vertical != AlignStart {
    87  			delta := float64(s.rect.Dy()) - float64(s.imgBounds.Dy())*scale
    88  			if s.vertical == AlignCenter {
    89  				thumbOp.GeoM.Translate(0, delta/2)
    90  			} else { // AlignEnd
    91  				thumbOp.GeoM.Translate(0, delta)
    92  			}
    93  		}
    94  		createThumb := s.thumb == nil
    95  		if !createThumb {
    96  			bounds := s.thumb.Bounds()
    97  			createThumb = bounds.Dx() != s.rect.Dx() || bounds.Dy() != s.rect.Dy()
    98  		}
    99  		if createThumb {
   100  			s.thumb = ebiten.NewImage(s.rect.Dx(), s.rect.Dy())
   101  		}
   102  		s.thumb.DrawImage(s.img, thumbOp)
   103  	}
   104  	screen.DrawImage(s.thumb, op)
   105  	return nil
   106  }
   107  

View as plain text