A rendering engine library for Go supporting both SDL2 and WebAssembly (HTML Canvas) targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
4.5 KiB

  1. package render
  2. import (
  3. "fmt"
  4. "image"
  5. "git.kirsle.net/go/render/event"
  6. )
  7. // Engine is the interface for the rendering engine, keeping SDL-specific stuff
  8. // far away from the core of Doodle.
  9. type Engine interface {
  10. Setup() error
  11. // Poll for events like keypresses and mouse clicks.
  12. Poll() (*event.State, error)
  13. GetTicks() uint32
  14. WindowSize() (w, h int)
  15. // Present presents the current state to the screen.
  16. Present() error
  17. // Clear the full canvas and set this color.
  18. Clear(Color)
  19. SetTitle(string)
  20. DrawPoint(Color, Point)
  21. DrawLine(Color, Point, Point)
  22. DrawRect(Color, Rect)
  23. DrawBox(Color, Rect)
  24. DrawText(Text, Point) error
  25. ComputeTextRect(Text) (Rect, error)
  26. // Texture caching.
  27. StoreTexture(name string, img image.Image) (Texturer, error)
  28. LoadTexture(name string) (Texturer, error)
  29. Copy(t Texturer, src, dst Rect)
  30. // Delay for a moment using the render engine's delay method,
  31. // implemented by sdl.Delay(uint32)
  32. Delay(uint32)
  33. // Tasks that the Setup function should defer until tear-down.
  34. Teardown()
  35. Loop() error // maybe?
  36. }
  37. // Texturer is a stored image texture used by the rendering engine while
  38. // abstracting away its inner workings.
  39. type Texturer interface {
  40. Size() Rect
  41. }
  42. // Rect has a coordinate and a width and height.
  43. type Rect struct {
  44. X int
  45. Y int
  46. W int
  47. H int
  48. }
  49. // NewRect creates a rectangle of size `width` and `height`. The X,Y values
  50. // are initialized to zero.
  51. func NewRect(width, height int) Rect {
  52. return Rect{
  53. W: width,
  54. H: height,
  55. }
  56. }
  57. func (r Rect) String() string {
  58. return fmt.Sprintf("Rect<%d,%d,%d,%d>",
  59. r.X, r.Y, r.W, r.H,
  60. )
  61. }
  62. // Point returns the rectangle's X,Y values as a Point.
  63. func (r Rect) Point() Point {
  64. return Point{
  65. X: r.X,
  66. Y: r.Y,
  67. }
  68. }
  69. // Bigger returns if the given rect is larger than the current one.
  70. func (r Rect) Bigger(other Rect) bool {
  71. // TODO: don't know why this is !
  72. return !(other.X < r.X || // Lefter
  73. other.Y < r.Y || // Higher
  74. other.W > r.W || // Wider
  75. other.H > r.H) // Taller
  76. }
  77. // Intersects with the other rectangle in any way.
  78. func (r Rect) Intersects(other Rect) bool {
  79. // Do a bidirectional compare.
  80. compare := func(a, b Rect) bool {
  81. var corners = []Point{
  82. NewPoint(b.X, b.Y),
  83. NewPoint(b.X, b.Y+b.H),
  84. NewPoint(b.X+b.W, b.Y),
  85. NewPoint(b.X+b.W, b.Y+b.H),
  86. }
  87. for _, pt := range corners {
  88. if pt.Inside(a) {
  89. return true
  90. }
  91. }
  92. return false
  93. }
  94. return compare(r, other) || compare(other, r) || false
  95. }
  96. // IsZero returns if the Rect is uninitialized.
  97. func (r Rect) IsZero() bool {
  98. return r.X == 0 && r.Y == 0 && r.W == 0 && r.H == 0
  99. }
  100. // Add another rect.
  101. func (r Rect) Add(other Rect) Rect {
  102. return Rect{
  103. X: r.X + other.X,
  104. Y: r.Y + other.Y,
  105. W: r.W + other.W,
  106. H: r.H + other.H,
  107. }
  108. }
  109. // Add a point to move the rect.
  110. func (r Rect) AddPoint(other Point) Rect {
  111. return Rect{
  112. X: r.X + other.X,
  113. Y: r.Y + other.Y,
  114. W: r.W,
  115. H: r.H,
  116. }
  117. }
  118. // SubtractPoint is the inverse of AddPoint. Use this only if you need to invert
  119. // the Point being added.
  120. //
  121. // This does r.X - other.X, r.Y - other.Y and keeps the width/height the same.
  122. func (r Rect) SubtractPoint(other Point) Rect {
  123. return Rect{
  124. X: r.X - other.X,
  125. Y: r.Y - other.Y,
  126. W: r.W,
  127. H: r.H,
  128. }
  129. }
  130. // Text holds information for drawing text.
  131. type Text struct {
  132. Text string
  133. Size int
  134. Color Color
  135. Padding int
  136. PadX int
  137. PadY int
  138. Stroke Color // Stroke color (if not zero)
  139. Shadow Color // Drop shadow color (if not zero)
  140. FontFilename string // Path to *.ttf file on disk
  141. }
  142. func (t Text) String() string {
  143. return fmt.Sprintf(`Text<"%s" %dpx %s>`, t.Text, t.Size, t.Color)
  144. }
  145. // IsZero returns if the Text is the zero value.
  146. func (t Text) IsZero() bool {
  147. return t.Text == "" && t.Size == 0 && t.Color == Invisible && t.Padding == 0 && t.PadX == 0 && t.PadY == 0 && t.Stroke == Invisible && t.Shadow == Invisible
  148. }
  149. // Common color names.
  150. var (
  151. Invisible = Color{}
  152. White = RGBA(255, 255, 255, 255)
  153. Grey = RGBA(153, 153, 153, 255)
  154. DarkGrey = RGBA(64, 64, 64, 255)
  155. Black = RGBA(0, 0, 0, 255)
  156. SkyBlue = RGBA(0, 153, 255, 255)
  157. Blue = RGBA(0, 0, 255, 255)
  158. DarkBlue = RGBA(0, 0, 153, 255)
  159. Red = RGBA(255, 0, 0, 255)
  160. DarkRed = RGBA(153, 0, 0, 255)
  161. Green = RGBA(0, 255, 0, 255)
  162. DarkGreen = RGBA(0, 153, 0, 255)
  163. Cyan = RGBA(0, 255, 255, 255)
  164. DarkCyan = RGBA(0, 153, 153, 255)
  165. Yellow = RGBA(255, 255, 0, 255)
  166. Orange = RGBA(255, 153, 0, 255)
  167. DarkYellow = RGBA(153, 153, 0, 255)
  168. Magenta = RGBA(255, 0, 255, 255)
  169. Purple = RGBA(153, 0, 153, 255)
  170. Pink = RGBA(255, 153, 255, 255)
  171. )