From a8b921e05bde775677b38691ac66b3584ef5da7a Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 17 Dec 2022 13:19:43 -0800 Subject: [PATCH] Simplify rope recalculator (still slow) --- chameleonic.p8 | 95 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/chameleonic.p8 b/chameleonic.p8 index c03b108..6aae30f 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -676,38 +676,76 @@ end function rope:_tidy_up_gen() if (self:busy()) return - for i=0,#self.ancs+1 do - local a=self:_anc(i) - a.dirty=true - end + if (self.under_destruction) return - local a=0 - while a<=#self.ancs+1 do - local anc=self:_anc(a) - if anc.dirty and #anc.todo==0 then - while not self.under_destruction and ( - self:_find_needed_anchors(a) or - self:_find_touched_anchors(a) or - self:_elide_point(a) - ) do end - - anc.dirty=false - a=0 - else + local settled=true + local touched={} + local loop=function(f) + local a=0 + while a<=#self.ancs+1 do + local anc=self:_anc(a) + if anc.dirty then + anc.seen=true + if self[f](self,a) then + settled=false anc.changed=true + end + end a+=1 end end + + local mark_unseen=function() + touched={} + for a=0,#self.ancs+1,1 do + local anc=self:_anc(a) + anc.seen=false + anc.changed=false + end + end + + local propagate_dirty=function(f) + for a=0,#self.ancs+1,1 do + local a1=self:_anc(a) + if a1.dirty then + local a0=self:_anc(a-1) + if (a0!=nil) a0.dirty=true + + local a2=self:_anc(a+1) + if (a2!=nil) a2.dirty=true + end + end + end + + while true do + settled=true + + mark_unseen() + propagate_dirty() + + loop("_find_needed_anchors") + loop("_find_touched_anchors") + loop("_elide_point") + + for a=0,#self.ancs+1,1 do + local anc=self:_anc(a) + if anc.seen then + anc.dirty=anc.changed + end + end + + if (settled) break + end end function rope:_drag1( i,x,y ) - local a_old=self:_anc(i) - local a_new={x=x,y=y} - if (_point_eq(a_old, a_new)) return + local a=self:_anc(i) + if (_point_eq(a, {x=x,y=y})) return - a_old.x=x - a_old.y=y + a.x=x + a.y=y + a.dirty=true end function rope:_find_needed_anchors(i) @@ -741,11 +779,9 @@ function rope:_find_needed_anchors(i) self:_can_stretch(a1,a2) then local id=self.id - add(self.ancs,{id=id,x=a1.x,y=a1.y,todo={}},i) + add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i) self.id+=1 - self:_anc(i-1).dirty=true - self:_anc(i+1).dirty=true return true end end @@ -765,12 +801,9 @@ function rope:_find_touched_anchors(i) -- and self:_can_stretch(p,a2) then local id=self.id - add(self.ancs,{id=id,x=a1.x,y=a1.y,todo={}},i) + add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i) self.id+=1 - self:_anc(i-1).dirty=true - self:_anc(i+1).dirty=true - return true end end @@ -808,8 +841,6 @@ function rope:_elide_point(i) end deli(self.ancs,i) - self:_anc(i-1).dirty=true - self:_anc(i).dirty=true return true end @@ -1034,7 +1065,6 @@ function rope:_tug() if force or not level:pcoll(x,y) then s.x=x s.y=y - s.dirty=true end return true end} @@ -1048,7 +1078,6 @@ function rope:_tug() end for node=ancs[i-1].ix-1,ancs[i].ix+1 do local anc=self:_anc(node) - if (anc!=nil) anc.dirty=true end return end