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