Skip to content

Commit 49965c4

Browse files
authored
Check for both points when moving within viewport (#15)
* Improved pathfinding * Check for both points when moving within viewport
1 parent 7a879cf commit 49965c4

File tree

3 files changed

+67
-58
lines changed

3 files changed

+67
-58
lines changed

grid.go

+14-11
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ func (p *page[T]) writeTile(grid *Grid[T], idx uint8, after Value) {
264264
Point: at,
265265
Value: after,
266266
},
267-
}, p.point, at)
267+
}, p.point)
268268
}
269269
}
270270

@@ -291,7 +291,7 @@ func (p *page[T]) mergeTile(grid *Grid[T], idx uint8, fn func(Value) Value) Valu
291291
Point: at,
292292
Value: after,
293293
},
294-
}, p.point, at)
294+
}, p.point)
295295
}
296296

297297
// Return the merged tile data
@@ -372,9 +372,15 @@ func (t Tile[T]) Range(fn func(T) error) error {
372372

373373
// Observers iterates over all views observing this tile
374374
func (t Tile[T]) Observers(fn func(view Observer[T])) {
375-
if t.data.IsObserved() {
376-
t.grid.observers.Each1(fn, t.data.point, t.Point())
375+
if !t.data.IsObserved() {
376+
return
377377
}
378+
379+
t.grid.observers.Each1(func(sub Observer[T]) {
380+
if sub.Viewport().Contains(t.Point()) {
381+
fn(sub)
382+
}
383+
}, t.data.point)
378384
}
379385

380386
// Add adds object to the set
@@ -394,7 +400,7 @@ func (t Tile[T]) Add(v T) {
394400
Value: value,
395401
},
396402
Add: v,
397-
}, t.data.point, at)
403+
}, t.data.point)
398404
}
399405
}
400406

@@ -415,7 +421,7 @@ func (t Tile[T]) Del(v T) {
415421
Value: value,
416422
},
417423
Del: v,
418-
}, t.data.point, at)
424+
}, t.data.point)
419425
}
420426
}
421427

@@ -449,16 +455,13 @@ func (t Tile[T]) Move(v T, dst Point) bool {
449455

450456
switch {
451457
case t.data == d.data || !d.data.IsObserved():
452-
t.grid.observers.Notify1(update, t.data.point, t.Point())
458+
t.grid.observers.Notify1(update, t.data.point)
453459
case !t.data.IsObserved():
454-
t.grid.observers.Notify1(update, d.data.point, d.Point())
460+
t.grid.observers.Notify1(update, d.data.point)
455461
default:
456462
t.grid.observers.Notify2(update, [2]Point{
457463
t.data.point,
458464
d.data.point,
459-
}, [2]Point{
460-
t.Point(),
461-
d.Point(),
462465
})
463466
}
464467
return true

view.go

+16-14
Original file line numberDiff line numberDiff line change
@@ -191,32 +191,36 @@ func (p *pubsub[T]) Unsubscribe(page Point, sub Observer[T]) bool {
191191
}
192192

193193
// Notify notifies listeners of an update that happened.
194-
func (p *pubsub[T]) Notify1(ev *Update[T], page, at Point) {
194+
func (p *pubsub[T]) Notify1(ev *Update[T], page Point) {
195195
p.Each1(func(sub Observer[T]) {
196-
sub.onUpdate(ev)
197-
}, page, at)
196+
viewport := sub.Viewport()
197+
if viewport.Contains(ev.New.Point) || viewport.Contains(ev.Old.Point) {
198+
sub.onUpdate(ev)
199+
}
200+
}, page)
198201
}
199202

200203
// Notify notifies listeners of an update that happened.
201-
func (p *pubsub[T]) Notify2(ev *Update[T], pages, locs [2]Point) {
204+
func (p *pubsub[T]) Notify2(ev *Update[T], pages [2]Point) {
202205
p.Each2(func(sub Observer[T]) {
203-
sub.onUpdate(ev)
204-
}, pages, locs)
206+
viewport := sub.Viewport()
207+
if viewport.Contains(ev.New.Point) || viewport.Contains(ev.Old.Point) {
208+
sub.onUpdate(ev)
209+
}
210+
}, pages)
205211
}
206212

207213
// Each iterates over each observer in a page
208-
func (p *pubsub[T]) Each1(fn func(sub Observer[T]), page, at Point) {
214+
func (p *pubsub[T]) Each1(fn func(sub Observer[T]), page Point) {
209215
if v, ok := p.m.Load(page.Integer()); ok {
210216
v.(*observers[T]).Each(func(sub Observer[T]) {
211-
if sub.Viewport().Contains(at) {
212-
fn(sub)
213-
}
217+
fn(sub)
214218
})
215219
}
216220
}
217221

218222
// Each2 iterates over each observer in a page
219-
func (p *pubsub[T]) Each2(fn func(sub Observer[T]), pages, locs [2]Point) {
223+
func (p *pubsub[T]) Each2(fn func(sub Observer[T]), pages [2]Point) {
220224
targets := p.tmp.Get().(map[Observer[T]]struct{})
221225
clear(targets)
222226
defer p.tmp.Put(targets)
@@ -232,9 +236,7 @@ func (p *pubsub[T]) Each2(fn func(sub Observer[T]), pages, locs [2]Point) {
232236

233237
// Invoke the callback for each observer, once
234238
for sub := range targets {
235-
if sub.Viewport().Contains(locs[0]) || sub.Viewport().Contains(locs[1]) {
236-
fn(sub)
237-
}
239+
fn(sub)
238240
}
239241
}
240242

view_test.go

+37-33
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ BenchmarkView/move-24 16141 74408 ns/op 0 B/op 0
1717
*/
1818
func BenchmarkView(b *testing.B) {
1919
m := mapFrom("300x300.png")
20-
v := NewView[string, string](m, "view 1")
20+
v := NewView(m, "view 1")
2121
v.Resize(NewRect(100, 0, 200, 100), nil)
2222

2323
go func() {
@@ -99,38 +99,6 @@ func TestView(t *testing.T) {
9999
assert.Equal(t, 0, len(v.Inbox))
100100
}
101101

102-
/*
103-
func TestObservers(t *testing.T) {
104-
ev := newObservers[uint32]()
105-
assert.NotNil(t, ev)
106-
107-
// Subscriber which does nothing
108-
var sub1 fakeView[uint32] = func(e *Update[uint32]) {}
109-
ev.Subscribe(&sub1)
110-
111-
// Counting subscriber
112-
var count int
113-
var sub2 fakeView[uint32] = func(e *Update[uint32]) {
114-
count += int(e.X)
115-
}
116-
ev.Subscribe(&sub2)
117-
118-
ev.Notify(&Update[uint32]{Point: At(1, 0)})
119-
ev.Notify(&Update[uint32]{Point: At(2, 0)})
120-
ev.Notify(&Update[uint32]{Point: At(3, 0)})
121-
122-
for count < 6 {
123-
time.Sleep(1 * time.Millisecond)
124-
}
125-
126-
assert.Equal(t, 6, count)
127-
ev.Unsubscribe(&sub2)
128-
129-
ev.Notify(&Update[uint32]{Point: At(2, 0)})
130-
assert.Equal(t, 6, count)
131-
}
132-
*/
133-
134102
func TestUpdates_Simple(t *testing.T) {
135103
m := mapFrom("300x300.png")
136104
c := counter(0)
@@ -317,6 +285,42 @@ func TestView_MoveTo(t *testing.T) {
317285
assert.NoError(t, v.Close())
318286
}
319287

288+
func TestView_Updates(t *testing.T) {
289+
m := mapFrom("300x300.png")
290+
v := NewView(m, "view 1")
291+
v.Resize(NewRect(10, 10, 15, 15), nil)
292+
293+
move := func(x1, y1, x2, y2 int16) {
294+
at, _ := m.At(x1, y1)
295+
at.Move("A", At(x2, y2))
296+
297+
assert.Equal(t, Update[string]{
298+
Old: ValueAt{Point: At(x1, y1)},
299+
New: ValueAt{Point: At(x2, y2)},
300+
Del: "A", Add: "A",
301+
}, <-v.Inbox)
302+
}
303+
304+
move(9, 12, 10, 12) // Enter from left edge
305+
move(10, 12, 9, 12) // Exit to left edge
306+
move(15, 12, 14, 12) // Enter from right edge
307+
move(14, 12, 15, 12) // Exit to right edge
308+
move(12, 9, 12, 10) // Enter from top edge
309+
move(12, 10, 12, 9) // Exit to top edge
310+
move(12, 15, 12, 14) // Enter from bottom edge
311+
move(12, 14, 12, 15) // Exit to bottom edge
312+
move(9, 9, 10, 10) // Enter from top-left diagonal
313+
move(10, 10, 9, 9) // Exit to top-left diagonal
314+
move(15, 9, 14, 10) // Enter from top-right diagonal
315+
move(14, 10, 15, 9) // Exit to top-right diagonal
316+
move(9, 15, 10, 14) // Enter from bottom-left diagonal
317+
move(10, 14, 9, 15) // Exit to bottom-left diagonal
318+
move(15, 15, 14, 14) // Enter from bottom-right diagonal
319+
move(14, 14, 15, 15) // Exit to bottom-right diagonal
320+
321+
assert.NoError(t, v.Close())
322+
}
323+
320324
func TestSizeUpdate(t *testing.T) {
321325
assert.Equal(t, 24, int(unsafe.Sizeof(Update[uint32]{})))
322326
}

0 commit comments

Comments
 (0)