github.com/acrespo/mobile@v0.0.0-20190107162257-dc0771356504/exp/sprite/sprite.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package sprite provides a 2D scene graph for rendering and animation. 6 // 7 // A tree of nodes is drawn by a rendering Engine, provided by another 8 // package. The OS-independent Go version based on the image package is: 9 // 10 // golang.org/x/mobile/exp/sprite/portable 11 // 12 // An Engine draws a screen starting at a root Node. The tree is walked 13 // depth-first, with affine transformations applied at each level. 14 // 15 // Nodes are rendered relative to their parent. 16 // 17 // Typical main loop: 18 // 19 // for each frame { 20 // quantize time.Now() to a clock.Time 21 // process UI events 22 // modify the scene's nodes and animations (Arranger values) 23 // e.Render(scene, t, sz) 24 // } 25 package sprite // import "golang.org/x/mobile/exp/sprite" 26 27 import ( 28 "image" 29 "image/draw" 30 31 "golang.org/x/mobile/event/size" 32 "golang.org/x/mobile/exp/f32" 33 "golang.org/x/mobile/exp/sprite/clock" 34 ) 35 36 type Arranger interface { 37 Arrange(e Engine, n *Node, t clock.Time) 38 } 39 40 type Texture interface { 41 Bounds() (w, h int) 42 Download(r image.Rectangle, dst draw.Image) 43 Upload(r image.Rectangle, src image.Image) 44 Release() 45 } 46 47 type SubTex struct { 48 T Texture 49 R image.Rectangle 50 } 51 52 type Engine interface { 53 Register(n *Node) 54 Unregister(n *Node) 55 56 LoadTexture(a image.Image) (Texture, error) 57 58 SetSubTex(n *Node, x SubTex) 59 SetTransform(n *Node, m f32.Affine) // sets transform relative to parent. 60 61 // Render renders the scene arranged at the given time, for the given 62 // window configuration (dimensions and resolution). 63 Render(scene *Node, t clock.Time, sz size.Event) 64 65 Release() 66 } 67 68 // A Node is a renderable element and forms a tree of Nodes. 69 type Node struct { 70 Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node 71 72 Arranger Arranger 73 74 // EngineFields contains fields that should only be accessed by Engine 75 // implementations. It is exported because such implementations can be 76 // in other packages. 77 EngineFields struct { 78 // TODO: separate TexDirty and TransformDirty bits? 79 Dirty bool 80 Index int32 81 SubTex SubTex 82 } 83 } 84 85 // AppendChild adds a node c as a child of n. 86 // 87 // It will panic if c already has a parent or siblings. 88 func (n *Node) AppendChild(c *Node) { 89 if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil { 90 panic("sprite: AppendChild called for an attached child Node") 91 } 92 last := n.LastChild 93 if last != nil { 94 last.NextSibling = c 95 } else { 96 n.FirstChild = c 97 } 98 n.LastChild = c 99 c.Parent = n 100 c.PrevSibling = last 101 } 102 103 // RemoveChild removes a node c that is a child of n. Afterwards, c will have 104 // no parent and no siblings. 105 // 106 // It will panic if c's parent is not n. 107 func (n *Node) RemoveChild(c *Node) { 108 if c.Parent != n { 109 panic("sprite: RemoveChild called for a non-child Node") 110 } 111 if n.FirstChild == c { 112 n.FirstChild = c.NextSibling 113 } 114 if c.NextSibling != nil { 115 c.NextSibling.PrevSibling = c.PrevSibling 116 } 117 if n.LastChild == c { 118 n.LastChild = c.PrevSibling 119 } 120 if c.PrevSibling != nil { 121 c.PrevSibling.NextSibling = c.NextSibling 122 } 123 c.Parent = nil 124 c.PrevSibling = nil 125 c.NextSibling = nil 126 }