home *** CD-ROM | disk | FTP | other *** search
- package com.livebrush.graphics
- {
- import com.livebrush.data.Settings;
- import com.livebrush.data.StateManager;
- import com.livebrush.data.Storable;
- import com.livebrush.graphics.canvas.Canvas;
- import com.livebrush.graphics.canvas.Layer;
- import com.livebrush.graphics.canvas.LineLayer;
- import com.livebrush.styles.DecoAsset;
- import com.livebrush.styles.Style;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.geom.Point;
-
- public class Line extends EventDispatcher implements Storable
- {
- public static const SMOOTH_LINE:String = "smooth";
-
- public static const STRAIGHT_LINE:String = "straight";
-
- public var newStrokeCount:int = 0;
-
- public var decoLoadCount:int;
-
- public var style:Style = null;
-
- public var changed:Boolean = false;
-
- public var type:String = "solid";
-
- public var strokes:Array;
-
- public var edges:Array;
-
- public var decoCount:int;
-
- public var created:Boolean = false;
-
- public var weight:Number = 1;
-
- public var lastStrokeLength:int = 0;
-
- public var lines:int = 2;
-
- public function Line(type:String = "solid", lines:int = 2, weight:Number = 1)
- {
- super();
- this.lastStrokeLength = 0;
- this.decoCount = 0;
- this.decoLoadCount = 0;
- this.lines = lines;
- this.type = type;
- this.weight = weight;
- this.strokes = [];
- this.edges = [];
- }
-
- public static function toStraightLine(line:Line) : Line
- {
- return convertLine(line,false);
- }
-
- public static function newLine(smooth:Boolean, type:String, lines:int, weight:Number) : Line
- {
- var line:Line = null;
- if(smooth)
- {
- line = new SmoothLine(type,lines,weight);
- }
- else
- {
- line = new Line(type,lines,weight);
- }
- return line;
- }
-
- public static function xmlToLine(xml:XML) : Line
- {
- var line:Line = Line.newLine(xml.@smooth == "true" ? true : false,xml.@type,Number(xml.@lines),Number(xml.@weight));
- line.setXML(xml.toXMLString());
- return line;
- }
-
- public static function convertLine(line:Line, smooth:Boolean) : Line
- {
- var newLine:Line = Line.newLine(smooth,line.type,line.lines,line.weight);
- for(var i:int = 0; i < line.length; newLine.edges.push(line.edges[i].copy()),i++)
- {
- }
- newLine.rebuild();
- return newLine;
- }
-
- public static function isSmoothLine(line:Line) : Boolean
- {
- return line is SmoothLine;
- }
-
- public static function toSmoothLine(line:Line) : SmoothLine
- {
- return SmoothLine(convertLine(line,true));
- }
-
- public function die() : void
- {
- this.created = false;
- while(this.edges.length > 0)
- {
- this.edges.pop().die();
- }
- while(this.strokes.length > 0)
- {
- this.strokes.pop().dieDecos();
- }
- this.lastStrokeLength = 0;
- this.changed = true;
- this.decoLoadCount = 0;
- }
-
- protected function invalidateEdgeStrokes(edgeIndex:int) : Array
- {
- var aStrokes:Array = this.getStrokeIndicesUsingEdge(edgeIndex);
- for(var i:int = 0; i < aStrokes.length; i++)
- {
- this.strokes[aStrokes[i]].changed = true;
- }
- return aStrokes;
- }
-
- public function removeEdgeDecos(indices:Array) : void
- {
- var edge:Edge = null;
- for(var i:int = 0; i < indices.length; i++)
- {
- edge = this.edges[indices[i]];
- if(edge.hasDecos)
- {
- edge.removeDecos();
- edge.decoGroup = null;
- }
- }
- this.changed = true;
- }
-
- public function get secondLastEdge() : Edge
- {
- return this.edges[Math.max(0,this.edges.length - 2)];
- }
-
- public function get firstStroke() : Stroke
- {
- return this.strokes[0];
- }
-
- public function simplify() : void
- {
- var newEdges:Array = null;
- if(this.length > 2)
- {
- newEdges = [];
- while(this.edges.length > 2)
- {
- newEdges.push(this.edges.shift());
- this.edges.shift().die();
- }
- if(this.edges.length > 1)
- {
- this.edges.shift().die();
- }
- newEdges.push(this.edges.shift());
- this.edges = newEdges;
- this.rebuild();
- }
- }
-
- public function get decosLoaded() : Boolean
- {
- return this.decoLoadCount == this.decoCount;
- }
-
- public function modifyEdgeColor(index:int, value:Number) : void
- {
- this.edges[index].color = value;
- }
-
- public function get firstEdge() : Edge
- {
- return this.edges[0];
- }
-
- public function modifyEdgeAlpha(index:int, value:Number) : void
- {
- this.edges[index].alpha = value;
- }
-
- public function deleteEdge(edge:Edge = null, i:int = -5) : void
- {
- var index:int = edge == null ? i : this.getEdgeIndex(edge);
- var aStrokes:Array = this.invalidateEdgeStrokes(index);
- if(this.length > 1)
- {
- if(aStrokes.length > 1)
- {
- this.strokes[aStrokes[1]].edge2 = this.strokes[aStrokes[0]].edge2;
- }
- this.strokes.splice(aStrokes[0],1)[0].die();
- }
- this.edges.splice(index,1)[0].die();
- this.lastStrokeLength = this.strokes.length;
- this.applyProps();
- }
-
- protected function decoComplete() : void
- {
- ++this.decoLoadCount;
- if(this.decoLoadCount == this.decoCount)
- {
- this.lineComplete();
- }
- }
-
- public function addEdge(edge:Edge, lockStart:Boolean = false) : void
- {
- var stroke:Stroke = null;
- this.edges.push(edge);
- if(this.edges.length == 3 && this is SmoothLine && !lockStart)
- {
- this.edges[0].angle = edge.angle;
- this.edges[1].angle = edge.angle;
- this.edges[0].applyProps();
- this.edges[1].applyProps();
- }
- else if(this.edges.length == 2 && !lockStart)
- {
- this.edges[0].angle = edge.angle;
- this.edges[0].applyProps();
- }
- if(this.length > 2)
- {
- stroke = this.addStroke([this.length - 1,this.length - 2,this.length - 3]);
- }
- else if(this.length > 1)
- {
- stroke = this.addStroke([this.length - 1,this.length - 2]);
- }
- this.created = this is SmoothLine ? this.edges.length > 2 : this.edges.length > 1;
- if(stroke != null)
- {
- if(stroke.decoGroup != null)
- {
- ++this.decoCount;
- if(!stroke.decoGroup.loaded)
- {
- stroke.decoGroup.addEventListener(Event.COMPLETE,this.decoCompleteHandler);
- }
- else
- {
- this.decoComplete();
- }
- }
- ++this.newStrokeCount;
- this.lastStrokeLength = this.strokes.length;
- }
- }
-
- public function modifyEdge(index:int, c:Point, a:Point, b:Point) : void
- {
- this.edges[index].transformEdge(c,a,b);
- this.invalidateEdgeIndex(index);
- }
-
- protected function deleteAllEdges() : void
- {
- this.die();
- }
-
- public function invalidateEdgeIndex(edgeIndex:int) : void
- {
- this.changed = true;
- if(this.length > 1)
- {
- this.invalidateEdgeStrokes(edgeIndex);
- }
- }
-
- public function rebuild() : void
- {
- this.created = false;
- for(var i:int = 0; i < this.edges.length; i++)
- {
- if(this.edges[i].decoGroup != null)
- {
- this.edges[i].decoGroup = this.edges[i].decoGroup.copy();
- }
- }
- var tempEdges:Array = this.edges.slice();
- while(this.strokes.length > 0)
- {
- this.strokes.pop().dieDecos();
- }
- this.edges = [];
- this.strokes = [];
- this.lastStrokeLength = 0;
- this.decoLoadCount = 0;
- for(i = 0; i < tempEdges.length; i++)
- {
- this.addEdge(tempEdges[i],true);
- }
- this.changed = true;
- }
-
- public function get lastEdgeIndex() : int
- {
- return this.length - 1;
- }
-
- protected function getEdgeIndices(edgeList:Array = null) : Array
- {
- var a:Array = [];
- var i:int = 0;
- if(edgeList == null)
- {
- for(i = 0; i < this.length; i++)
- {
- a.push(i);
- }
- }
- else
- {
- for(i = 0; i < edgeList.length; i++)
- {
- a.push(this.getEdgeIndex(edgeList[i]));
- }
- }
- return a;
- }
-
- public function applyProps() : void
- {
- this.changed = true;
- for(var i:int = 0; i < this.strokes.length; i++)
- {
- if(this.strokes[i].changed)
- {
- this.strokes[i].applyProps();
- }
- }
- }
-
- public function drawWireframe() : void
- {
- var vectors:Sprite = null;
- var s:int = 0;
- if(this.edges.length > 1)
- {
- vectors = Canvas.GLOBAL_CANVAS.wireframe;
- for(s = 0; s < this.strokes.length; s++)
- {
- if(s == 0)
- {
- this.strokes[s].drawWireframe(Stroke.START);
- }
- else if(s == this.strokes.length - 1)
- {
- this.strokes[s].drawWireframe(Stroke.END);
- }
- else
- {
- this.strokes[s].drawWireframe(Stroke.MIDDLE);
- }
- }
- vectors.graphics.moveTo(this.firstStroke.edge2.a.x,this.firstStroke.edge2.a.y);
- vectors.graphics.lineTo(this.firstStroke.edge2.b.x,this.firstStroke.edge2.b.y);
- vectors.graphics.moveTo(this.lastStroke.edge1.a.x,this.lastStroke.edge1.a.y);
- vectors.graphics.lineTo(this.lastStroke.edge1.b.x,this.lastStroke.edge1.b.y);
- }
- }
-
- public function invalidateEdge(edge:Edge) : void
- {
- this.changed = true;
- if(this.length > 1)
- {
- this.invalidateEdgeStrokes(this.getEdgeIndex(edge));
- }
- }
-
- public function getSVG() : XML
- {
- return new XML(<g/>);
- }
-
- protected function addStroke(edgeIndices:Array) : Stroke
- {
- var stroke:Stroke = null;
- if(this.length > 3 && this is SmoothLine)
- {
- stroke = new SmoothStroke(this.edges[edgeIndices[0]],this.edges[edgeIndices[1]],this.edges[edgeIndices[2]],this.type,this.weight);
- this.strokes.push(stroke);
- }
- else if(this.length > 2 && !(this is SmoothLine))
- {
- stroke = new Stroke(this.edges[edgeIndices[0]],this.edges[edgeIndices[1]],this.edges[edgeIndices[2]],this.type,this.weight);
- this.strokes.push(stroke);
- }
- else if(this.length == 2)
- {
- stroke = new Stroke(this.edges[edgeIndices[0]],this.edges[edgeIndices[1]],null,this.type,this.weight);
- this.strokes.push(stroke);
- }
- else if(this.length == 3 && this is SmoothLine)
- {
- this.strokes[0].die();
- stroke = this.strokes[0] = new SmoothStroke(this.edges[edgeIndices[0]],this.edges[edgeIndices[1]],this.edges[edgeIndices[2]],this.type,this.weight);
- }
- return stroke;
- }
-
- public function drawNew(layer:Layer) : void
- {
- var s:int = 0;
- if(this.length > 1)
- {
- for(s = this.lastStrokeLength - 1; s < this.strokes.length; s++)
- {
- if(s == 0)
- {
- this.strokes[s].draw(layer,Stroke.START);
- }
- else
- {
- this.strokes[s].draw(layer);
- }
- }
- }
- this.newStrokeCount = 0;
- }
-
- public function subdivide() : void
- {
- var edge1:Edge = null;
- var edge2:Edge = null;
- var newEdge:Edge = null;
- var subEdges:Array = null;
- var newEdges:Array = null;
- var i:int = 0;
- if(this.length > 1)
- {
- subEdges = [];
- newEdges = [];
- for(i = 1; i < this.length; i++)
- {
- edge1 = this.edges[i - 1];
- edge2 = this.edges[i];
- newEdge = Edge.interpolate(edge1,edge2,0.5);
- subEdges.push(newEdge);
- }
- do
- {
- newEdges.push(this.edges.shift());
- if(subEdges.length > 0)
- {
- newEdges.push(subEdges.shift());
- }
- }
- while(this.edges.length > 0);
-
- this.edges = newEdges;
- this.rebuild();
- }
- }
-
- protected function getStrokeIndicesUsingEdge(edgeIndex:int) : Array
- {
- var edgeStrokes:Array = [];
- if(!(this is SmoothLine))
- {
- if(edgeIndex > 0 && edgeIndex < this.lastEdgeIndex)
- {
- edgeStrokes = [edgeIndex - 1,edgeIndex];
- }
- else if(edgeIndex == 0)
- {
- edgeStrokes.push(0);
- }
- else if(edgeIndex == this.lastEdgeIndex)
- {
- edgeStrokes.push(edgeIndex - 1);
- }
- }
- else if(this is SmoothLine)
- {
- if(this.length < 4)
- {
- edgeStrokes = [0];
- }
- else if(edgeIndex > 1 && edgeIndex < this.lastEdgeIndex - 1)
- {
- edgeStrokes = [edgeIndex - 2,edgeIndex - 1,edgeIndex];
- }
- else if(edgeIndex == 0)
- {
- edgeStrokes.push(0);
- }
- else if(edgeIndex == this.lastEdgeIndex)
- {
- edgeStrokes.push(edgeIndex - 2);
- }
- else if(edgeIndex == 1)
- {
- edgeStrokes = [0,1];
- }
- else if(edgeIndex == this.lastEdgeIndex - 1)
- {
- edgeStrokes = [this.strokes.length - 2,this.strokes.length - 1];
- }
- }
- return edgeStrokes;
- }
-
- public function draw(layer:Layer) : void
- {
- var s:int = 0;
- if(this.length > 1)
- {
- for(s = 0; s < this.strokes.length; s++)
- {
- if(s == 0)
- {
- this.strokes[s].draw(layer,Stroke.START);
- }
- else if(s == this.strokes.length - 1)
- {
- this.strokes[s].draw(layer,Stroke.END);
- }
- else
- {
- this.strokes[s].draw(layer,Stroke.MIDDLE);
- }
- }
- this.newStrokeCount = 0;
- }
- this.changed = false;
- }
-
- protected function lineComplete() : void
- {
- dispatchEvent(new Event(Event.COMPLETE,true,false));
- }
-
- public function addEdgeAt(index:int, pt:Point = null) : void
- {
- var aStrokes:Array = null;
- var newEdge:Edge = null;
- var newStroke:Stroke = null;
- if(index != this.lastEdgeIndex)
- {
- aStrokes = this.invalidateEdgeStrokes(index);
- newEdge = Edge.interpolate(this.edges[index],this.edges[index + 1],0.5);
- if(pt != null)
- {
- newEdge.modify(pt,newEdge.angleRads,newEdge.width);
- newEdge.applyProps();
- }
- this.edges.splice(index + 1,0,newEdge);
- if(aStrokes.length > 1)
- {
- newStroke = new Stroke(this.edges[index + 1],this.edges[index],null,this.type,this.weight);
- this.strokes[aStrokes[1]].edge2 = newEdge;
- }
- else
- {
- newStroke = new Stroke(this.edges[index + 2],this.edges[index + 1],null,this.type,this.weight);
- this.strokes[aStrokes[0]].edge1 = newEdge;
- }
- this.strokes.splice(aStrokes[0] + 1,0,newStroke);
- this.lastStrokeLength = this.strokes.length;
- this.applyProps();
- }
- }
-
- public function addEdgeDeco(index:int, decoAsset:DecoAsset, initObj:Settings) : void
- {
- this.invalidateEdgeStrokes(index);
- this.edges[index].addDeco(decoAsset,initObj);
- this.applyProps();
- }
-
- public function setXML(xml:String) : void
- {
- var stroke:XML = null;
- var newEdge:Edge = null;
- var lineXML:XML = new XML(xml);
- try
- {
- this.die();
- }
- catch(e:Error)
- {
- }
- for each(stroke in lineXML.*)
- {
- stroke.@lines = Number(lineXML.@lines);
- newEdge = Edge.xmlToEdge(stroke.toXMLString());
- this.addEdge(newEdge,true);
- }
- }
-
- public function setEdgeXML(index:int, xml:String, setDecos:Boolean = false) : void
- {
- var xmlObj:XML = new XML(xml);
- xmlObj.@lines = this.lines;
- this.edges[index].setXMLDecoBool(xmlObj.toXMLString(),setDecos);
- this.invalidateEdgeIndex(index);
- }
-
- protected function getEdgeIndex(edge:Edge) : int
- {
- return this.edges.indexOf(edge);
- }
-
- public function getXML() : XML
- {
- var lineXML:XML = new XML(<line lines={this.lines} type={this.type} smooth={this is SmoothLine} weight={this.weight}/>);
- for(var i:int = 0; i < this.edges.length; i++)
- {
- lineXML.appendChild(this.edges[i].getXML());
- }
- return lineXML;
- }
-
- public function applyStyle(style:Style) : void
- {
- this.weight = style.strokeStyle.weight;
- this.lines = style.strokeStyle.lines;
- this.type = style.strokeStyle.strokeType;
- for(var i:int = 0; i < this.length; i++)
- {
- this.edges[i].lines = this.lines;
- this.edges[i].applyProps();
- }
- }
-
- protected function decoCompleteHandler(e:Event) : void
- {
- e.target.removeEventListener(e.type,this.decoCompleteHandler);
- this.decoComplete();
- }
-
- public function get length() : int
- {
- return this.edges.length;
- }
-
- public function deleteEdges(delEdgeList:Array, indices:Boolean = false) : void
- {
- var edgeIndices:Array = null;
- var i:int = 0;
- if(!indices)
- {
- edgeIndices = this.getEdgeIndices(delEdgeList);
- }
- else
- {
- edgeIndices = delEdgeList.slice();
- }
- StateManager.addItem(function(state:Object):void
- {
- var l:LineLayer = LineLayer(state.canvasManager.getLayer(state.activeLayerDepth));
- l.line.setXML(state.data.lineXML.toXMLString());
- l.setup();
- },function(state:Object):void
- {
- var l:LineLayer = LineLayer(state.canvasManager.getLayer(state.activeLayerDepth));
- l.line.deleteEdges(state.data.edgeIndices,true);
- l.setup();
- },-1,{
- "lineXML":this.getXML(),
- "edgeIndices":edgeIndices
- });
- if(delEdgeList.length == this.edges.length)
- {
- this.deleteAllEdges();
- }
- else
- {
- for(i = int(delEdgeList.length - 1); i >= 0; i--)
- {
- if(!indices)
- {
- this.deleteEdge(delEdgeList[i]);
- }
- else
- {
- this.deleteEdge(null,delEdgeList[i]);
- }
- }
- }
- }
-
- public function get hasDecos() : Boolean
- {
- return this.decoCount > 0;
- }
-
- public function stringType() : String
- {
- return this is SmoothLine ? SMOOTH_LINE : STRAIGHT_LINE;
- }
-
- public function get lastEdge() : Edge
- {
- return this.edges[this.edges.length - 1];
- }
-
- public function get lastStroke() : Stroke
- {
- return this.strokes[this.strokes.length - 1];
- }
-
- public function copy(includeDecos:Boolean = true, basic:Boolean = false) : Line
- {
- var newLine:Line = null;
- if(basic)
- {
- newLine = new Line(this.type,2,1);
- }
- else
- {
- newLine = new Line(this.type,this.lines,this.weight);
- }
- for(var i:int = 0; i < this.edges.length; i++)
- {
- newLine.addEdge(this.edges[i].copy(includeDecos,basic),true);
- }
- return newLine;
- }
- }
- }
-
-