Changeset - 0a47ec94fc63
[Not reviewed]
default
0 2 0
Drew Perttula - 12 years ago 2013-06-10 09:28:11
drewp@bigasterisk.com
move all point editing into Curve. fix manip to never try to make points have the same X. add check in Curve that points never have the same X or crossing X
Ignore-this: 75ad005fd9d35a61ecef82bf8ddae3f4
2 files changed with 63 insertions and 22 deletions:
0 comments (0 inline, 0 general)
light9/curvecalc/curve.py
Show inline comments
 
@@ -72,6 +72,22 @@ class Curve(object):
 
        self.points.insert(i,new_pt)
 
        return i
 

	
 
    def set_points(self, updates):
 
        for i, pt in updates:
 
            self.points[i] = pt
 
            
 
        x = None
 
        for p in self.points:
 
            if p[0] <= x:
 
                raise ValueError("overlapping points")
 
            x = p[0]
 

	
 
    def pop_point(self, i):
 
        return self.points.pop(i)
 
            
 
    def remove_point(self, pt):
 
        self.points.remove(pt)
 
            
 
    def indices_between(self, x1, x2, beyond=0):
 
        leftidx = max(0, bisect(self.points, (x1,None)) - beyond)
 
        rightidx = min(len(self.points),
light9/curvecalc/curveview.py
Show inline comments
 
@@ -56,7 +56,7 @@ class Sketch:
 
                to_remove.append(i)
 

	
 
        for i in to_remove:
 
            self.curveview.curve.points.remove(pts[i])
 
            self.curveview.curve.remove_point(pts[i])
 
            finalPoints.remove(pts[i])
 

	
 
        # the simplified curve may now be too far away from some of
 
@@ -153,24 +153,35 @@ class SelectManip(object):
 
            left = origPts[0][1][0]
 
            right = origPts[-1][1][0]
 
            width = right - left
 
            dontCross = .001
 

	
 
            clampLo = left if param == 'right' else self.dragRange[0]
 
            clampHi = right if param == 'left' else self.dragRange[1]
 

	
 
            def clamp(x, lo, hi):
 
                return max(lo, min(hi, x))
 
            
 
            mouseT = self.getWorldTime(event.x)
 
            clampedT = max(clampLo, min(clampHi, mouseT))
 
            clampedT = clamp(mouseT, clampLo + dontCross, clampHi - dontCross)
 

	
 
            dt = clampedT - self.dragStartTime
 

	
 
            if param == 'x':
 
                self.setPoints((i, (orig[0] + dt, orig[1]))
 
                               for i, orig in origPts)
 
            elif param == 'left':
 
                self.setPoints((i, (left + dt +
 
                                    (orig[0] - left) / width * (width - dt),
 
                self.setPoints((
 
                    i,
 
                    (left + dt +
 
                     (orig[0] - left) / width *
 
                     clamp(width - dt, dontCross, right - clampLo - dontCross),
 
                                    orig[1])) for i, orig in origPts)
 
            elif param == 'right':
 
                self.setPoints((i, (left +
 
                                    (orig[0] - left) / width * (width + dt),
 
                self.setPoints((
 
                    i,
 
                    (left +
 
                     (orig[0] - left) / width *
 
                     clamp(width + dt, dontCross, clampHi - left - dontCross),
 
                                    orig[1])) for i, orig in origPts)
 
            elif param == 'top':
 
                v = self.getWorldValue(event.y)
 
@@ -186,8 +197,9 @@ class SelectManip(object):
 
                dt = mouseT - self.dragStartTime
 
                rad = width / 2
 
                tMid = left + rad
 
                maxScl = (rad + self.maxPointMove) / rad
 
                newWidth = max(0, min((rad + dt) / rad, maxScl)) * width
 
                maxScl = (rad + self.maxPointMove - dontCross) / rad
 
                newWidth = max(dontCross / width,
 
                               min((rad + dt) / rad, maxScl)) * width
 
                self.setPoints((i,
 
                                (tMid +
 
                                 ((orig[0] - left) / width - .5) * newWidth,
 
@@ -465,7 +477,7 @@ class Curveview(object):
 
        idx = self.curve.index_before(self.current_time())
 
        if idx is not None:
 
            pos = self.curve.points[idx]
 
            self.curve.points[idx] = (pos[0], value)
 
            self.curve.set_points([(idx, (pos[0], value))])
 
            self.update_curve()
 

	
 
    def slider_in(self, curve, value=None):
 
@@ -516,8 +528,11 @@ class Curveview(object):
 
        self.selectionChanged()
 

	
 
    def getDragRange(self, idxs):
 
        """if you're dragging these points, what's the most time you
 
        can move left and right before colliding with another point"""
 
        """
 
        if you're dragging these points, what's the most time you can move
 
        left and right before colliding (exactly) with another
 
        point
 
        """
 
        maxLeft = maxRight = 99999
 
        cp = self.curve.points
 
        for i in idxs:
 
@@ -535,8 +550,7 @@ class Curveview(object):
 
        return maxLeft, maxRight
 

	
 
    def setPoints(self, updates):
 
        for i, pt in updates:
 
            self.curve.points[i] = pt
 
        self.curve.set_points(updates)
 
        self.update_curve()
 
        
 
    def selectionChanged(self):
 
@@ -669,13 +683,12 @@ class Curveview(object):
 
        
 
        self.size = self.canvas.get_allocation()
 
 
 
        cp = self.curve.points
 
        visible_x = (self.world_from_screen(0,0)[0],
 
                     self.world_from_screen(self.size.width, 0)[0])
 

	
 
        visible_idxs = self.curve.indices_between(visible_x[0], visible_x[1],
 
                                                  beyond=1)
 
        visible_points = [cp[i] for i in visible_idxs]
 
        visible_points = [self.curve.points[i] for i in visible_idxs]
 

	
 
        if getattr(self, 'curveGroup', None):
 
            self.curveGroup.remove()
 
@@ -874,7 +887,7 @@ class Curveview(object):
 
        while idxs:
 
            i = idxs.pop()
 

	
 
            self.curve.points.pop(i)
 
            self.curve.pop_point(i)
 
            newsel = []
 
            newidxs = []
 
            for si in range(len(self.selected_points)):
 
@@ -936,9 +949,11 @@ class Curveview(object):
 
            return
 
        if not event.state & 256:
 
            return # not lmb-down
 
        cp = self.curve.points
 
        moved=0
 

	
 
        # this way is accumulating error and also making it harder to
 
        # undo (e.g. if the user moves far out of the window or
 
        # presses esc or something). Instead, we should be resetting
 
        # the points to their start pos plus our total offset.
 
        cur = self.world_from_screen(event.x, event.y)
 
        if self.last_mouse_world:
 
            delta = (cur[0] - self.last_mouse_world[0],
 
@@ -947,6 +962,16 @@ class Curveview(object):
 
            delta = 0,0
 
        self.last_mouse_world = cur
 
        
 
        moved = self.translate_points(delta)
 
        
 
        if moved:
 
            self.update_curve()
 

	
 
    def translate_points(self, delta):
 
        moved = False
 
        
 
        cp = self.curve.points
 
        updates = []
 
        for idx in self.selected_points:
 

	
 
            newp = [cp[idx][0] + delta[0], cp[idx][1] + delta[1]]
 
@@ -957,10 +982,10 @@ class Curveview(object):
 
                continue
 
            if idx<len(cp)-1 and newp[0] >= cp[idx+1][0]:
 
                continue
 
            moved=1
 
            cp[idx] = tuple(newp)
 
        if moved:
 
            self.update_curve()
 
            moved = True
 
            updates.append((idx, tuple(newp)))
 
        self.curve.set_points(updates)
 
        return moved
 

	
 
    def unselect(self):
 
        self.select_indices([])
0 comments (0 inline, 0 general)