...

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  	if s.rect.Dx() == 0 || s.rect.Dy() == 0 {
    67  		return nil // The Sprite has no size. Don't draw anything.
    68  	}
    69  
    70  	op := &ebiten.DrawImageOptions{}
    71  	op.GeoM.Translate(float64(s.rect.Min.X), float64(s.rect.Min.Y))
    72  	if s.imgBounds.Dx() == s.rect.Dx() && s.imgBounds.Dy() == s.rect.Dy() {
    73  		screen.DrawImage(s.img, op)
    74  		return nil
    75  	} else if s.thumb == nil || s.thumbBounds.Dx() != s.rect.Dx() || s.thumbBounds.Dy() != s.rect.Dy() {
    76  		scale, yScale := float64(s.rect.Dx())/float64(s.imgBounds.Dx()), float64(s.rect.Dy())/float64(s.imgBounds.Dy())
    77  		if yScale < scale {
    78  			scale = yScale
    79  		}
    80  		thumbOp := &ebiten.DrawImageOptions{}
    81  		thumbOp.GeoM.Scale(scale, scale)
    82  		if s.horizontal != AlignStart {
    83  			delta := float64(s.rect.Dx()) - float64(s.imgBounds.Dx())*scale
    84  			if s.horizontal == AlignCenter {
    85  				thumbOp.GeoM.Translate(delta/2, 0)
    86  			} else { // AlignEnd
    87  				thumbOp.GeoM.Translate(delta, 0)
    88  			}
    89  		}
    90  		if s.vertical != AlignStart {
    91  			delta := float64(s.rect.Dy()) - float64(s.imgBounds.Dy())*scale
    92  			if s.vertical == AlignCenter {
    93  				thumbOp.GeoM.Translate(0, delta/2)
    94  			} else { // AlignEnd
    95  				thumbOp.GeoM.Translate(0, delta)
    96  			}
    97  		}
    98  		createThumb := s.thumb == nil
    99  		if !createThumb {
   100  			bounds := s.thumb.Bounds()
   101  			createThumb = bounds.Dx() != s.rect.Dx() || bounds.Dy() != s.rect.Dy()
   102  		}
   103  		if createThumb {
   104  			s.thumb = ebiten.NewImage(s.rect.Dx(), s.rect.Dy())
   105  		}
   106  		s.thumb.DrawImage(s.img, thumbOp)
   107  		s.thumbBounds = s.thumb.Bounds()
   108  	}
   109  	screen.DrawImage(s.thumb, op)
   110  	return nil
   111  }
   112  

View as plain text