improve display performance, particularly when panning the map and when dragging...
authorRichard Fairhurst <richard@systemed.net>
Mon, 6 Dec 2010 22:25:50 +0000 (22:25 +0000)
committerRichard Fairhurst <richard@systemed.net>
Mon, 6 Dec 2010 22:25:50 +0000 (22:25 +0000)
net/systemeD/halcyon/EntityUI.as
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/WayUI.as
net/systemeD/potlatch2/controller/DragWayNode.as

index 152320d..bc23043 100644 (file)
@@ -20,6 +20,7 @@ package net.systemeD.halcyon {
                protected var layer:Number=0;                                   // map layer
                protected var suspended:Boolean=false;                  // suspend redrawing?
                protected var redrawDue:Boolean=false;                  // redraw called while suspended?
+               protected var clearLimit:uint=0;                                // sprite to clear back to
                public var paint:MapPaint;                                              // reference to parent MapPaint
                public var ruleset:RuleSet;                                             // reference to ruleset in operation
                public var interactive:Boolean=true;                    // does object respond to clicks?
@@ -146,13 +147,18 @@ package net.systemeD.halcyon {
                }
 
                public function removeSprites():void {
-                       while (sprites.length>0) {
+                       while (sprites.length>clearLimit) {
                                var d:DisplayObject=sprites.pop();
                                if (d.parent) { d.parent.removeChild(d); }
                        }
-                       listenSprite.hitArea=null;
-                       hitzone=null;
+                       if (clearLimit==0) {
+                               listenSprite.hitArea=null;
+                               hitzone=null;
+                       }
                }
+               
+               public function protectSprites():void { clearLimit=sprites.length; }
+               public function unprotectSprites():void { clearLimit=0; }
 
                protected function offsetSprites(x:Number, y:Number):void {
                        for each (var d:DisplayObject in sprites) {
@@ -205,7 +211,9 @@ package net.systemeD.halcyon {
                
                public function redraw():Boolean {
                        if (suspended) { redrawDue=true; return false; }
-                       return doRedraw();
+                       var r:Boolean=doRedraw();
+                       cacheSpritesAsBitmap(true);
+                       return r;
                }
                
                public function doRedraw():Boolean {
@@ -229,6 +237,12 @@ package net.systemeD.halcyon {
                public function invalidateStyleList():void {
                        styleList=null;
                }
+               
+               private function cacheSpritesAsBitmap(cache:Boolean):void {
+                       for each (var s:DisplayObject in sprites) {
+                               if (s!=listenSprite) s.cacheAsBitmap=cache;
+                       }
+               }
 
        }
 
index 59f93e6..1a6015e 100644 (file)
@@ -1,6 +1,7 @@
 package net.systemeD.halcyon {
 
        import flash.text.TextField;
+       import flash.geom.Rectangle;
        import flash.display.DisplayObjectContainer;
        import flash.display.Loader;
        import flash.display.Sprite;
@@ -89,6 +90,7 @@ package net.systemeD.halcyon {
                        gotEnvironment(null);
 
                        addEventListener(Event.ENTER_FRAME, everyFrame);
+                       scrollRect=new Rectangle(0,0,800,600);
         }
 
                public function gotEnvironment(r:Object):void {
@@ -164,12 +166,12 @@ package net.systemeD.halcyon {
                // Recalculate co-ordinates from new Flash origin
 
                public function updateCoords(tx:Number,ty:Number):void {
-                       x=tx; y=ty;
+                       setScrollRectXY(tx,ty);
 
-                       edge_t=coord2lat(-y          );
-                       edge_b=coord2lat(-y+mapheight);
-                       edge_l=coord2lon(-x          );
-                       edge_r=coord2lon(-x+mapwidth );
+                       edge_t=coord2lat(-ty          );
+                       edge_b=coord2lat(-ty+mapheight);
+                       edge_l=coord2lon(-tx          );
+                       edge_r=coord2lon(-tx+mapwidth );
                        setCentre();
 
                        tileset.update();
@@ -181,9 +183,23 @@ package net.systemeD.halcyon {
                        updateCoords(cx,cy);
                }
                
+               private function setScrollRectXY(tx:Number,ty:Number):void {
+                       var w:Number=scrollRect.width;
+                       var h:Number=scrollRect.height;
+                       scrollRect=new Rectangle(-tx,-ty,w,h);
+               }
+               private function setScrollRectSize(width:Number,height:Number):void {
+                       var sx:Number=scrollRect.x ? scrollRect.x : 0;
+                       var sy:Number=scrollRect.y ? scrollRect.y : 0;
+                       scrollRect=new Rectangle(sx,sy,width,height);
+               }
+               
+               private function getX():Number { return -scrollRect.x; }
+               private function getY():Number { return -scrollRect.y; }
+               
                private function setCentre():void {
-                       centre_lat=coord2lat(-y+mapheight/2);
-                       centre_lon=coord2lon(-x+mapwidth/2);
+                       centre_lat=coord2lat(-getY()+mapheight/2);
+                       centre_lon=coord2lon(-getX()+mapwidth/2);
                        this.dispatchEvent(new MapEvent(MapEvent.MOVE, {lat:centre_lat, lon:centre_lon, scale:scale, minlon:edge_l, maxlon:edge_r, minlat:edge_b, maxlat:edge_t}));
                }
                
@@ -192,7 +208,7 @@ package net.systemeD.halcyon {
                }
 
                private function moveMap(dx:Number,dy:Number):void {
-                       updateCoords(x+dx,y+dy);
+                       updateCoords(getX()+dx,getY()+dy);
                        updateEntityUIs(false, false);
                        download();
                }
@@ -210,16 +226,14 @@ package net.systemeD.halcyon {
                public function lat2coord(a:Number):Number      { return -(lat2latp(a)-basey)*scalefactor; }
                public function coord2lat(a:Number):Number      { return latp2lat(a/-scalefactor+basey); }
 
-//             public function centrelat(o) { return coord2lat((yradius-_root.map._y-o)/Math.pow(2,_root.scale-13)); }
-//             public function centrelon(o) { return coord2lon((xradius-_root.map._x-o)/Math.pow(2,_root.scale-13)); }
-
 
                // ------------------------------------------------------------------------------------------
                // Resize map size based on current stage and height
 
                public function updateSize(w:uint, h:uint):void {
-                       mapwidth = w; centre_lon=coord2lon(-x+w/2);
-                       mapheight= h; centre_lat=coord2lat(-y+h/2);
+                       mapwidth = w; centre_lon=coord2lon(-getX()+w/2);
+                       mapheight= h; centre_lat=coord2lat(-getY()+h/2);
+                       setScrollRectSize(w,h);
 
                        this.dispatchEvent(new MapEvent(MapEvent.RESIZE, {width:w, height:h}));
                        
@@ -286,6 +300,21 @@ package net.systemeD.halcyon {
                        if (paint.wayuis[way.id]) paint.wayuis[way.id].setHighlightOnNodes(settings);
         }
 
+               public function protectWay(way:Way):void {
+                       if (paint.wayuis[way.id]) paint.wayuis[way.id].protectSprites();
+               }
+
+               public function unprotectWay(way:Way):void {
+                       if (paint.wayuis[way.id]) paint.wayuis[way.id].unprotectSprites();
+               }
+               
+               public function limitWayDrawing(way:Way,except:Number=NaN,only:Number=NaN):void {
+                       if (!paint.wayuis[way.id]) return;
+                       paint.wayuis[way.id].drawExcept=except;
+                       paint.wayuis[way.id].drawOnly  =only;
+                       paint.wayuis[way.id].redraw();
+               }
+
                /* Protect Entities and EntityUIs against purging. This prevents the currently selected items
                   from being purged even though they're off-screen. */
 
@@ -432,13 +461,13 @@ package net.systemeD.halcyon {
                public function mouseDownHandler(event:MouseEvent):void {
                        if (!_draggable) { return; }
                        dragstate=NOT_MOVED;
-                       lastxmouse=mouseX; downX=stage.mouseX;
-                       lastymouse=mouseY; downY=stage.mouseY;
+                       lastxmouse=stage.mouseX; downX=stage.mouseX;
+                       lastymouse=stage.mouseY; downY=stage.mouseY;
                        downTime=new Date().getTime();
                }
         
                public function mouseUpHandler(event:MouseEvent=null):void {
-                       if (dragstate==DRAGGING) { moveMap(0,0); }
+                       if (dragstate==DRAGGING) { moveMap(x,y); }
                        dragstate=NOT_DRAGGING;
                }
         
@@ -455,9 +484,8 @@ package net.systemeD.halcyon {
                                dragstate=DRAGGING;
                        }
                        
-                       x+=mouseX-lastxmouse;
-                       y+=mouseY-lastymouse;
-                       lastxmouse=mouseX; lastymouse=mouseY;
+                       setScrollRectXY(getX()+stage.mouseX-lastxmouse,getY()+stage.mouseY-lastymouse);
+                       lastxmouse=stage.mouseX; lastymouse=stage.mouseY;
                        setCentre();
                }
         
index 748a548..ce398c4 100644 (file)
@@ -18,6 +18,10 @@ package net.systemeD.halcyon {
                public var centroid_x:Number;                           // centroid
                public var centroid_y:Number;                           //  |
                public var heading:Array=new Array();           // angle at each node
+               public var drawExcept:Number;                           // vertex to draw exclusively, or not at all (used by DragWayNode)
+               public var drawOnly:Number;                                     //  |
+               private var indexStart:uint;                            //  |
+               private var indexEnd:uint;                                      //  |
                public var nameformat:TextFormat;
                private var recalculateDue:Boolean=false;
 
@@ -211,6 +215,14 @@ package net.systemeD.halcyon {
                                if (tags['layer']) { layer=Math.min(Math.max(tags['layer'],paint.minlayer),paint.maxlayer); }
                        }
 
+                       // Do we have to draw all nodes in the way?
+                       if (isNaN(drawOnly)) {
+                               indexStart=0; indexEnd=Way(entity).length; 
+                       } else {
+                               indexStart=Math.max(0,drawOnly-1);
+                               indexEnd  =Math.min(drawOnly+2,Way(entity).length);
+                       }
+
                        // Iterate through each sublayer, drawing any styles on that layer
                        var drawn:Boolean;
                        var multis:Array=entity.findParentRelationsOfType('multipolygon','outer');
@@ -286,7 +298,7 @@ package net.systemeD.halcyon {
                        // Draw icons
                        var r:Number;
                        var nodeSelected:int=stateClasses["nodeSelected"];
-                       for (var i:uint = 0; i < Way(entity).length; i++) {
+                       for (var i:uint = indexStart; i < indexEnd; i++) {
                 var node:Node = Way(entity).getNode(i);
                                var nodeStateClasses:Object={};
 //                             if (i==0) { nodetags['_heading']= heading[i]; }
@@ -315,16 +327,33 @@ package net.systemeD.halcyon {
                // Draw solid polyline
                
                public function solidLines(g:Graphics,inners:Array):void {
-                       solidLine(g,entity as Way);
-                       for each (var w:Way in inners) { solidLine(g,w); }
+                       solidLine(g);
+                       for each (var w:Way in inners) { solidLineOtherWay(g,w); }
                }
 
-               private function solidLine(g:Graphics,w:Way):void {
-                       if (w.length==0) { return; }
-            var node:Node = w.getNode(0);
+               private function solidLine(g:Graphics):void {
+                       if (indexEnd==0) { return; }
+                       var way:Way=entity as Way;
+                       
+            var node:Node = way.getNode(indexStart);
+                       g.moveTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
+                       for (var i:uint = indexStart+1; i < indexEnd; i++) {
+                node = way.getNode(i);
+                               if (!isNaN(drawExcept) && (i-1==drawExcept || i==drawExcept)) {
+                                       g.moveTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
+                               } else {
+                                       g.lineTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
+                               }
+                       }
+               }
+
+               private function solidLineOtherWay(g:Graphics,way:Way):void {
+                       if (way.length==0) { return; }
+                       
+                       var node:Node = way.getNode(indexStart);
                        g.moveTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
-                       for (var i:uint = 1; i < w.length; i++) {
-                node = w.getNode(i);
+                       for (var i:uint = 1; i < way.length; i++) {
+                               node = way.getNode(i);
                                g.lineTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
                        }
                }
@@ -338,18 +367,19 @@ package net.systemeD.halcyon {
                        var a:Number, xc:Number, yc:Number;
                        var curx:Number, cury:Number;
                        var dx:Number, dy:Number, segleft:Number=0;
-                       var i:int=0;
+                       var i:int=indexStart;
 
-            var node:Node = way.getNode(0);
-            var nextNode:Node = way.getNode(0);
+            var node:Node = way.getNode(i);
+            var nextNode:Node = way.getNode(i);
                        g.moveTo(paint.map.lon2coord(node.lon), paint.map.latp2coord(node.latp));
-                       while (i < way.length-1 || segleft>0) {
+                       while (i < indexEnd-1 || segleft>0) {
                                if (dashleft<=0) {      // should be ==0
                                        if (dc.length==0) { dc=dashes.slice(0); }
                                        dashleft=dc.shift();
                                        if (draw) { segments.push([curx,cury,dx,dy]); }
                                        draw=!draw;
                                }
+                               if (i==drawExcept || i==drawExcept+1) { draw=false; }
                                if (segleft<=0) {       // should be ==0
                     node = way.getNode(i);
                     nextNode = way.getNode(i+1);
index 1d35efc..3d10871 100644 (file)
@@ -117,10 +117,15 @@ package net.systemeD.potlatch2.controller {
                        originalLon = draggingNode.lon;
 
                        controller.map.setHighlightOnNodes(parentWay, { selectedway: true } );
+                       controller.map.limitWayDrawing(parentWay, draggingIndex);
                        controller.map.setHighlight(draggingNode, { selected: true } );
+                       controller.map.protectWay(parentWay);
+                       controller.map.limitWayDrawing(parentWay, NaN, draggingIndex);
                        Globals.vars.root.addDebug("**** -> "+this);
         }
         override public function exitState(newState:ControllerState):void {
+                       controller.map.unprotectWay(parentWay);
+                       controller.map.limitWayDrawing(parentWay);
                        controller.map.setHighlightOnNodes(parentWay, { selectedway: false } );
                        controller.map.setHighlight(draggingNode, { selected: false } );
                        Globals.vars.root.addDebug("**** <- "+this);