From 297d9b8f66062a374a880333e0cec9290d1ea3dc Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Mon, 6 Dec 2010 22:25:50 +0000 Subject: [PATCH] improve display performance, particularly when panning the map and when dragging a node in a way (some issues to sort out with the latter still) --- net/systemeD/halcyon/EntityUI.as | 22 +++++-- net/systemeD/halcyon/Map.as | 66 +++++++++++++------ net/systemeD/halcyon/WayUI.as | 54 +++++++++++---- .../potlatch2/controller/DragWayNode.as | 5 ++ 4 files changed, 112 insertions(+), 35 deletions(-) diff --git a/net/systemeD/halcyon/EntityUI.as b/net/systemeD/halcyon/EntityUI.as index 152320d8..bc230432 100644 --- a/net/systemeD/halcyon/EntityUI.as +++ b/net/systemeD/halcyon/EntityUI.as @@ -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; + } + } } diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as index 59f93e67..1a6015ed 100644 --- a/net/systemeD/halcyon/Map.as +++ b/net/systemeD/halcyon/Map.as @@ -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(); } diff --git a/net/systemeD/halcyon/WayUI.as b/net/systemeD/halcyon/WayUI.as index 748a5482..ce398c44 100644 --- a/net/systemeD/halcyon/WayUI.as +++ b/net/systemeD/halcyon/WayUI.as @@ -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); diff --git a/net/systemeD/potlatch2/controller/DragWayNode.as b/net/systemeD/potlatch2/controller/DragWayNode.as index 1d35efcd..3d108712 100644 --- a/net/systemeD/potlatch2/controller/DragWayNode.as +++ b/net/systemeD/potlatch2/controller/DragWayNode.as @@ -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); -- 2.30.0