/* * Copyright 2008 (c) Lance Pollard * www.systemsofseven.com/blog * www.4ddesignlab.com * LanceJPollard@gmail.com * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package com.fourD.core { import com.fourD.animators.IAnimator; import com.fourD.animators.TweenMaxAnimator; import com.fourD.utils.TweenUtil; import flash.events.*; import gs.*; import mx.core.IDataRenderer; import mx.core.UIComponent; [DefaultProperty("front")] public class FourDComponent extends UIComponent implements IDataRenderer { // The _containers are necessary to make the face switching work right private var _frontContainer:UIComponent; private var _backContainer:UIComponent; private var controllerChanged:Boolean; private var defaultBack:Boolean; private var _animator:IAnimator; [Bindable] public function get animator():IAnimator { return _animator; } public function set animator(value:IAnimator):void { _animator = value; } /** * Tweens can be arrays of objects * or just simple objects (if you don't want complex animations) * Stack as many as you want together and you can * have hardcore animation forward and backward (without having to reverse) */ private var tweensChanged:Boolean; private var tweenParamsChanged:Boolean; private var _tweens:Array; [Bindable] public function get tweens():* { return _tweens; } public function set tweens(value:*):void { trace("tweens set"); for (var i:int=0; i < value.length; i++) { value[i].onUpdate = setSideVisibility; } _tweens = value; tweensChanged = true; invalidateProperties(); } private var _tweenParams:Array; [Bindable] public function get tweenParams():Array { return _tweenParams; } public function set tweenParams(value:Array):void { _tweenParams = value; tweenParamsChanged = true; invalidateProperties(); } private var pivotXChanged:Boolean; private var pivotYChanged:Boolean; private var frontChanged:Boolean; private var backChanged:Boolean; public var side:String = "front"; /** These are the components used as the plane faces. * Front = main target, Back = optional other target */ private var _front:*; [Bindable] public function set front(value:*):void { _front = value; trace("fourDComponent front set = " + _front); // to keep things consistent, since it inherits the view property frontChanged = true; invalidateProperties(); invalidateSize(); invalidateDisplayList(); } public function get front():* { return _front; } private var _back:*; [Bindable] public function set back(value:*):void { _back = value; backChanged = true; invalidateProperties(); invalidateSize(); invalidateDisplayList(); } public function get back():* { return _back; } private var _pivotX:String; [Inspectable(defaultValue="center", enumeration="center,right,left")] [Bindable] public function set pivotX(value:String):void { _pivotX = value; pivotXChanged = true; invalidateProperties(); } public function get pivotX():String { return _pivotX; } private var _pivotY:String; [Inspectable(defaultValue="center", enumeration="center,top,bottom")] [Bindable] public function set pivotY(value:String):void { _pivotY = value; pivotYChanged = true; invalidateProperties(); } public function get pivotY():String { return _pivotY; } private var _data:Object; [Bindable] public function get data():Object { return _data; } public function set data(value:Object):void { _data = value; } public function FourDComponent() { _backContainer = new UIComponent(); _frontContainer = new UIComponent(); trace("id of fourD is: " + flash.utils.getDethis)); } override protected function createChildren():void { super.createChildren(); if (back == null) { back = new UIComponent(); defaultBack = true; } if (animator == null) { animator = new TweenMaxAnimator(); } } override protected function commitProperties():void { super.commitProperties(); // import to set this to false // it prevents calling invalidateTargetAndParentDisplayList(); // which fucks everything up this.includeInLayout = false; if (backChanged) { backChanged = false; back.includeInLayout = false; if (back is FourDComponent) { addChild(back); } else { // _backContainer.rotationY = 180; // this is what's slowing things down _backContainer.includeInLayout = false; _backContainer.addChild(back); _backContainer.rotationY = 180; _backContainer.visible = false; addChild(_backContainer); } if (back is IDataRenderer) { IDataRenderer(back).data = data; } } if (frontChanged) { frontChanged = false; front.includeInLayout = false; if (front is FourDComponent) { addChild(front); } else { _frontContainer.includeInLayout = false; _frontContainer.addChild(front); addChild(_frontContainer); } if (front is IDataRenderer) { IDataRenderer(front).data = data; } } if (tweensChanged) { tweensChanged = false; } if (tweenParamsChanged) { tweenParamsChanged = false; updateTweenParams(); } } override protected function measure():void { super.measure(); if(front) { // an explicit width/height in the view becomes measured width/height for the component // ie. component declared width/height trumps view preferences measuredWidth = front.getExplicitOrMeasuredWidth(); measuredHeight = front.getExplicitOrMeasuredHeight(); measuredMinWidth = isNaN( front.explicitWidth ) ? front.minWidth : front.explicitWidth; measuredMinHeight = isNaN( front.explicitHeight ) ? front.minHeight : front.explicitHeight; } } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); if (front) { front.setActualSize(unscaledWidth, unscaledHeight); UIComponent(front).invalidateDisplayList(); } if (pivotXChanged) { if (front is FourDComponent) { return } pivotXChanged = false; if (pivotX == "center") { front.x = (front.width/2)*-1; back.x = (back.width/2)*-1; } else if (pivotX == "left") { } else if (pivotX == "right") { front.x = (front.width)*-1; back.x = (back.width)*-1; } else {} } if (pivotYChanged) { if (front is FourDComponent) { return } pivotYChanged = false; if (pivotY == "center") { front.y = (front.height/2)*-1; back.y = (back.height/2)*-1 } else if (pivotY == "top") { } else if (pivotY == "bottom") { front.y = (front.height)*-1; } else {} } } override public function setActualSize(w:Number, h:Number):void { super.setActualSize(w, h); if (front) { front.setActualSize(w, h); } if (!defaultBack) { back.setActualSize(w, h); } } protected function updateTweens():void { } protected function updateTweenParams():void { // animator so you can create handlers for the onComplete/onStart/onClick params TweenUtil.resolveParams(tweens, tweenParams, animator); } public function tween(event:MouseEvent=null):void { if (event) { if (!TweenUtil.validateTweenTarget(event.target, this)) { return; } } animator.tween(tweens, tweenParams, this); } private function setSideVisibility():void{ if (this.rotationY >= 90 || this.rotationX >= 90) { side = "back" _backContainer.visible = true; _frontContainer.visible = false; _backContainer.rotationY = 180; } else if (this.rotationY < 90 || this.rotationX < 90) { side = "front" _backContainer.visible = false; _frontContainer.visible = true; _backContainer.rotationY = 0; } } } }