mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
restorable: Bug fix: wrong topological sort (#359)
This commit is contained in:
parent
91b5d985fe
commit
ad1f1263f7
@ -228,6 +228,14 @@ func (p *Image) dependsOn(target *Image) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Image) dependingImages() map[*Image]struct{} {
|
||||
r := map[*Image]struct{}{}
|
||||
for _, c := range p.drawImageHistory {
|
||||
r[c.image] = struct{}{}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (p *Image) hasDependency() bool {
|
||||
if p.stale {
|
||||
return false
|
||||
@ -275,7 +283,7 @@ func (p *Image) restore() error {
|
||||
gimg.Fill(p.baseColor)
|
||||
}
|
||||
for _, c := range p.drawImageHistory {
|
||||
// c.image.image must be already restored.
|
||||
// All dependencies must be already resolved.
|
||||
if c.image.hasDependency() {
|
||||
panic("not reached")
|
||||
}
|
||||
|
@ -93,37 +93,45 @@ func (i *images) restore() error {
|
||||
|
||||
// Let's do topological sort based on dependencies of drawing history.
|
||||
// There should not be a loop since cyclic drawing makes images stale.
|
||||
current := map[*Image]struct{}{}
|
||||
toBeDetermined := map[*Image]struct{}{}
|
||||
type edge struct {
|
||||
source *Image
|
||||
target *Image
|
||||
}
|
||||
images := map[*Image]struct{}{}
|
||||
for i := range i.images {
|
||||
images[i] = struct{}{}
|
||||
}
|
||||
edges := map[edge]struct{}{}
|
||||
for t := range images {
|
||||
for s := range t.dependingImages() {
|
||||
edges[edge{source: s, target: t}] = struct{}{}
|
||||
}
|
||||
}
|
||||
sorted := []*Image{}
|
||||
for img := range i.images {
|
||||
if img.hasDependency() {
|
||||
toBeDetermined[img] = struct{}{}
|
||||
continue
|
||||
for len(images) > 0 {
|
||||
// current repesents images that have no incoming edges.
|
||||
current := map[*Image]struct{}{}
|
||||
for i := range images {
|
||||
current[i] = struct{}{}
|
||||
}
|
||||
current[img] = struct{}{}
|
||||
sorted = append(sorted, img)
|
||||
}
|
||||
// TODO: How to confirm that there is no loop?
|
||||
for len(current) > 0 {
|
||||
next := map[*Image]struct{}{}
|
||||
// TODO: This is inefficient. Get all edges from the source first.
|
||||
// (*Image).childImages?
|
||||
for source := range current {
|
||||
for target := range toBeDetermined {
|
||||
if target.dependsOn(source) {
|
||||
next[target] = struct{}{}
|
||||
for e := range edges {
|
||||
if _, ok := current[e.target]; ok {
|
||||
delete(current, e.target)
|
||||
}
|
||||
}
|
||||
for i := range current {
|
||||
delete(images, i)
|
||||
sorted = append(sorted, i)
|
||||
}
|
||||
for img := range next {
|
||||
sorted = append(sorted, img)
|
||||
delete(toBeDetermined, img)
|
||||
removed := []edge{}
|
||||
for e := range edges {
|
||||
if _, ok := current[e.source]; ok {
|
||||
removed = append(removed, e)
|
||||
}
|
||||
current = next
|
||||
}
|
||||
if len(toBeDetermined) > 0 {
|
||||
panic("not reached")
|
||||
for _, e := range removed {
|
||||
delete(edges, e)
|
||||
}
|
||||
}
|
||||
for _, img := range sorted {
|
||||
if err := img.restore(); err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user