/
drawHeap.go
146 lines (133 loc) · 3.71 KB
/
drawHeap.go
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package render
import (
"container/heap"
"image"
"image/draw"
"sync"
)
// A RenderableHeap managed a set of renderables to be drawn in explicit layered
// order, using an internal heap to manage that order.
type RenderableHeap struct {
rs []Renderable
toPush []Renderable
static bool
addLock sync.RWMutex
}
// NewHeap creates a new renderableHeap. The static boolean represents whether
// this heap exists relative to the viewport or not-- if true, an element at 40,40
// will always be at 40,40. If false, when the viewport moves, the element will
// move opposite the direction of the viewport.
func NewHeap(static bool) *RenderableHeap {
rh := new(RenderableHeap)
rh.rs = make([]Renderable, 0)
rh.toPush = make([]Renderable, 0)
rh.static = static
rh.addLock = sync.RWMutex{}
return rh
}
//Add stages a new Renderable to add to the heap
func (rh *RenderableHeap) Add(r Renderable, layer int) Renderable {
r.SetLayer(layer)
rh.addLock.Lock()
rh.toPush = append(rh.toPush, r)
rh.addLock.Unlock()
return r
}
//Replace adds a Renderable and removes an old one
func (rh *RenderableHeap) Replace(r1, r2 Renderable, layer int) {
rh.Add(r2, layer)
r1.UnDraw()
}
// Satisfying the Heap interface
//Len gets the length of the current heap
func (rh *RenderableHeap) Len() int { return len(rh.rs) }
//Less returns whether a renderable at index i is at a lower layer than the one at index j
func (rh *RenderableHeap) Less(i, j int) bool { return rh.rs[i].GetLayer() < rh.rs[j].GetLayer() }
//Swap moves two locations
func (rh *RenderableHeap) Swap(i, j int) { rh.rs[i], rh.rs[j] = rh.rs[j], rh.rs[i] }
//Push adds to the renderable heap
func (rh *RenderableHeap) Push(r interface{}) {
// defer func() {
// if x := recover(); x != nil {
// dlog.Error("Invalid Memory address pushed to Draw Heap")
// }
// }()
if r == nil {
return
}
// This can cause a 'name offset base pointer out of range' error
// Maybe having incrementing sizes instead of appending could help that?
rh.rs = append(rh.rs, r.(Renderable))
}
//Pop pops from the heap
func (rh *RenderableHeap) Pop() interface{} {
n := len(rh.rs)
x := rh.rs[n-1]
rh.rs = rh.rs[0 : n-1]
return x
}
// PreDraw parses through renderables to be pushed
// and adds them to the drawheap.
func (rh *RenderableHeap) PreDraw() {
// defer func() {
// if x := recover(); x != nil {
// dlog.Error("Invalid Memory Address in Draw heap")
// // This does not work-- all addresses following the bad address
// // at i are also bad
// //rh.toPush = rh.toPush[i+1:]
// rh.toPush = []Renderable{}
// }
// }()
rh.addLock.Lock()
for _, r := range rh.toPush {
if r != nil {
heap.Push(rh, r)
}
}
rh.toPush = make([]Renderable, 0)
rh.addLock.Unlock()
}
// Copy on a renderableHeap does not include any of its elements,
// as renderables cannot be copied.
func (rh *RenderableHeap) Copy() Addable {
return NewHeap(rh.static)
}
func (rh *RenderableHeap) draw(world draw.Image, viewPos image.Point, screenW, screenH int) {
newRh := &RenderableHeap{}
if rh.static {
for rh.Len() > 0 {
rp := heap.Pop(rh)
if rp != nil {
r := rp.(Renderable)
if r.GetLayer() != Undraw {
r.Draw(world)
heap.Push(newRh, r)
}
}
}
} else {
vx := float64(-viewPos.X)
vy := float64(-viewPos.Y)
for rh.Len() > 0 {
intf := heap.Pop(rh)
if intf != nil {
r := intf.(Renderable)
if r.GetLayer() != Undraw {
x2 := int(r.GetX())
y2 := int(r.GetY())
w, h := r.GetDims()
x := w + x2
y := h + y2
if x > viewPos.X && y > viewPos.Y &&
x2 < viewPos.X+screenW && y2 < viewPos.Y+screenH {
if InDrawPolygon(x, y, x2, y2) {
r.DrawOffset(world, vx, vy)
}
}
heap.Push(newRh, r)
}
}
}
}
rh.rs = newRh.rs
}