scratch-flash/3d_render_src/ChildRender.as
2014-06-24 17:31:18 -04:00

151 lines
4.7 KiB
ActionScript

/*
* Scratch Project Editor and Player
* Copyright (C) 2014 Massachusetts Institute of Technology
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package {
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.geom.Rectangle;
public class ChildRender extends BitmapData {
private const allowPartial:Boolean = true;
private const maxSize:uint = 1022;
private const halfSize:uint = maxSize >> 1;
private var orig_width:Number;
private var orig_height:Number;
private var orig_bounds:Rectangle;
public var inner_x:Number;
public var inner_y:Number;
public var inner_w:Number;
public var inner_h:Number;
public var scale:Number;
public function ChildRender(w:Number, h:Number, dispObj:DisplayObject, penLayer:DisplayObject, b:Rectangle) {
orig_width = w;
orig_height = h;
orig_bounds = b;
scale = 1;
reset(dispObj, penLayer);
super(Math.ceil(Math.min(w, maxSize)), Math.ceil(Math.min(h, maxSize)), true, 0);
}
public function reset(dispObj:DisplayObject, penLayer:DisplayObject):void {
inner_x = inner_y = 0;
inner_w = inner_h = 1;
if(!allowPartial) {
if(orig_width > maxSize || orig_height > maxSize)
scale = maxSize / Math.max(orig_width, orig_height);
return;
}
// Is it too large and needs to be partially rendered?
var bounds:Rectangle;
if(orig_width > maxSize || orig_height > maxSize) {
bounds = getVisibleBounds(dispObj, penLayer);
bounds.inflate(halfSize - bounds.width / 2, 0);
if(bounds.x < 0) {
bounds.width += bounds.x;
bounds.x = 0;
}
if(bounds.right > orig_width)
bounds.width += orig_width - bounds.right;
inner_x = bounds.x / orig_width;
inner_w = maxSize / orig_width;
}
if(orig_height > maxSize) {
if(!bounds) bounds = getVisibleBounds(dispObj, penLayer);
bounds.inflate(0, halfSize - bounds.height / 2);
if(bounds.y < 0) {
bounds.height += bounds.y;
bounds.y = 0;
}
if(bounds.bottom > orig_height)
bounds.height += orig_height - bounds.bottom;
inner_y = bounds.y / orig_height;
inner_h = maxSize / orig_height;
}
}
public function isPartial():Boolean {
return allowPartial && (width < orig_width || height < orig_height);
}
public function get renderWidth():Number {
return (width > orig_width ? orig_width : width);
}
public function get renderHeight():Number {
return (height > orig_height ? orig_height : height);
}
public function needsResize(w:Number, h:Number):Boolean {
if(width > orig_width && Math.ceil(w) > width) {
return true;
}
if(height > orig_height && Math.ceil(h) > height) {
return true;
}
return false;
}
public function needsRender(dispObj:DisplayObject, w:Number, h:Number, penLayer:DisplayObject):Boolean {
if(inner_x == 0 && inner_y == 0 && inner_w == 1 && inner_h == 1) return false;
var renderRect:Rectangle = new Rectangle(inner_x*w, inner_y*h, inner_w*w, inner_h*h);
renderRect.width += 0.001;
renderRect.height += 0.001;
var stageRect:Rectangle = getVisibleBounds(dispObj, penLayer);
var containsStage:Boolean = renderRect.containsRect(stageRect);
return !containsStage;
}
private function getVisibleBounds(dispObj:DisplayObject, penLayer:DisplayObject):Rectangle {
var visibleBounds:Rectangle = penLayer.getBounds(dispObj);
var tl:Point = orig_bounds.topLeft;
visibleBounds.offset(-tl.x, -tl.y);
if(visibleBounds.x < 0) {
visibleBounds.width += visibleBounds.x;
visibleBounds.x = 0;
}
if(visibleBounds.y < 0) {
visibleBounds.height += visibleBounds.y;
visibleBounds.y = 0;
}
if(visibleBounds.right > orig_width) {
visibleBounds.width += orig_width - visibleBounds.right;
}
if(visibleBounds.bottom > orig_height) {
visibleBounds.height += orig_height - visibleBounds.bottom;
}
visibleBounds.x *= dispObj.scaleX;
visibleBounds.y *= dispObj.scaleY;
visibleBounds.width *= dispObj.scaleX;
visibleBounds.height *= dispObj.scaleY;
return visibleBounds;
}
}
}