Flex 4까지 공식 배포되기 시작했지만 Flex 역사가 수년이 지났음에도 불구하고 버젓한 한글문서라고는 flexdocs.kr 가 다였습니다. 일본어를 어렵게 번역하고 수번이나 수정하면서 한 것들이라 중간중간 필요한 내용이 누락되거나 단어가 이상한 것도 있었지만 그동안 Flex 학습에 큰 도움을 준 것은 사실입니다. 아쉽게도 Flex 3에 대한 한글문서가 잠깐 선보였다가 갑자기 사라진 뒤로는 이제 더이상 Flex관련 한글 문서는 기대하기 힘들겠다 생각했습니다.

그러나 열이아빠님께서 이러한 분위기를 깨뜨려주셨습니다.

개인적으로 진행하시던 Flex 4 한글 문서화를 공개하신겁니다. Flex 4 한글 문서화 프로젝트는 단순히 한글 문서를 만드는데만 그친다고 보지 않습니다. 개발자들끼리 뭔가 새로운 네트워크를 만들어주는 좋은 장치일 수 있습니다. 그래서 저도 동참하기로 마음먹었고 미약하게나마 지원해 드릴 수 있는 부분은 적극적으로 하려고 합니다.

Flex 2, 3에 대한 개발경험이 있으신 분이시고 번역작업에 동참하시고 싶으신 분이라면 언제든지 참여하실 수 있습니다. 자세한 내용은 다음 글을 참고하세요.

어도비에 한글 문서가 없다고 불만만 가지지 말고 이런 상황을 잘 이용할 필요가 있습니다. 단순한 작업 같지만 매우 중요하고, 그러면서 뭔가 다른 개발자들에게 도움이 될 수 있는 일이면서 자신의 인맥을 넓힐 수 있는 중요한 계기가 될 수 있습니다.

많은 Flex 개발자 분들의 참여를 부탁드려요.

글쓴이 : 지돌스타(http://blog.jidolstar.com)



어제 무사히 Flex 기술세미나를 마쳤습니다.

(비트기술세미나라고 명칭되어 있었네요. 그게 좀 전달이 안된 것 같네요.)

 

무려 200개의 자리를 꽉 채울 정도로 많은 분들이 밤 늦은 시간까지 경청하시고 가셨습니다. 정말 수고 많으셨어요. ^^

 

세미나에서 옥상훈님께서는 UX(User Experience)에 대해서 매우 자세히 잘 말씀해주셨습니다. UX에 대해 다시 한번 생각해보는 계기가 되었구요. 또 배준균님께서 BlazeDS에 대해 현업에서 어떻게 쓰일지에 대해서 자세히 말씀해 주셨습니다. 아쉽게도 인터넷이 잘 안되어서 난감해 하셨는데... 알고보니 그거 유동IP가 아니라 고정IP였다는... ^^

 

저는 Flex 4에 대해 설명드렸습니다. 사실 저도 Flex 4를 공부한다는 마음을 가지고 이번 세미나 주제로 다룬겁니다. 덕분에 저도 열심히 공부할 수 있었고 많은 분들에게 Flex 4에 대해서 처음으로 소개할 수 있게 되어서 기분도 좋았답니다. 하지만 시간이 촉박해서 마지막에 질의시간을 가지지 못한 것 죄송합니다.

 

Flex 4에 대해 잠깐 언급했고 Flex 4를 이용해서 개발하는 툴인 Flash Builder 4와 Flash Catalyst에 대해서 소개했습니다. CSS, FXG, Namespace, State, Data Binding, Effect, None Visual Component 다루는 법, Spark Component와 Spark Layout 등에 대해서 약간 맛배기 정도로 다뤘습니다. 사실 소개드린 하나하나가 무거운 주제로 다루어도 몇시간씩은 해야하는 것들입니다. 그러므로 더 깊이 있는 공부를 위해서 관련 내용을 프리젠테이션에 있는 링크를 보시고 습득하시길 바래요.


아래 파일은 어제 발표했던 프리젠테이션 파일입니다.


 

아래 파일들은 어제 다뤘던 예제입니다.

 

invalid-file

출처 : http://evtimmy.com/2009/06/wheellayout-source-and-quick-mashup/

 

아래 두개는 시간이 없어서 소개하지 못한것인데 Flex 4를 이용해 컴포넌트를 만든 예제입니다. (제가 만든거 아닙니다. ^^)

invalid-file

출처 : http://www.hulstkamp.com/2009/07/09/custom-popup-rating-component-in-spark-flex-4-gumbo/464

invalid-file

참고 : http://blog.jidolstar.com/570

 

위 예제를 실험하기 위해서는 Flash Builder 4를 다운 받아야겠지요?
http://www.adoberia.co.kr/pds/down.html?src=text&kw=000026 

위의 예제는 Flash Builder 4에서 import 해서 사용할 수 있는데 다음과 같이 해보세요.

  1. Flash Builder 4를 실행
  2. File > New > Flex Project를 통해 Project를 생성
  3. File > Import > Other 선택
  4. 새창이 뜨면 General > Archive File 선택 후 Next 버튼 클릭
  5. "From archive file"에서 Browse 버튼을 클릭하여 위 Zip파일중 하나를 선택
  6. "Into folder" 에서 Browse 버튼을 눌러 새로 생성한 프로젝트를 선택후 Finish 버튼 클릭 (진행도중 Overwrite 경고 뜨면 모두 Overwrite합니다.)
  7. src 폴더에 들어간 mxml파일은 모두 Application입니다. 이중 하나를 열고 Run 메뉴에서 실행하거나 Ctrl+F11로 실행하면 되겠습니다.

 

다른 분의 자료는 http://okgosu.net 에서 제공이 될겁니다.

 

개인적인 소망이 있습니다. 많은 분들이 제 블로그를 통해 Flex 관련자료를 접하고 계신것 잘 알고 있습니다. 하지만 저도 다른 사람들을 통해서 많이 배우고 싶은 사람입니다. 서로 소통이 되어야 진정으로 정보공유라고 생각하고 바람직한 방향이라고 생각해요. 앞으로 Flex 4든 Flash Platform에 대한 어떤 자료든지 아시는 것있다면 함께 공유해서 함께 커갔으면 합니다. 어짜피 기술이라는 것은 시간이 지나면 또 바뀌고 사라질 수도 있잖아요? 자기만 알고 있다고 해서 다 좋은 것은 아니라는 겁니다. Flex 5, Flex 6가 나올때도 한국에서 한국 블로거 또는 카페등을 통해 매일 피상적인 정보만 얻어가는 정도나 질문에만 답해야하는 그런 상황이 반복된다면 정말 암울할 것 같아요. 정보생산의 주체가 적어도 어제 참석한 분들의 수만 되도 한국의 IT 미래는 매우 밝아질 것입니다.

 

 

012345

 

글쓴이 : 지돌스타(http://blog.jidolstar.com/579)

InsideRIA에 올라온 Getting started with Spark skins 의 글을 읽고 따라해보았다.

 

아래는 Skin 소스이다. com.jidolstar.skins.MyButtonSkin으로 이름을 지었다.

<?xml version="1.0" encoding="utf-8"?>
<s:Skin 
	xmlns:fx="http://ns.adobe.com/mxml/2009" 
	xmlns:s="library://ns.adobe.com/flex/spark" 
	xmlns:mx="library://ns.adobe.com/flex/halo" 
	>
	<fx:Metadata>
		[HostComponent("spark.components.Button")]
	</fx:Metadata>
	
	<s:states>
		<mx:State name="up"/>
		<mx:State name="down"/>
		<mx:State name="over"/>
		<mx:State name="disabled"/>
	</s:states>
	
	<s:filters>
		<s:DropShadowFilter quality="3"
			alpha="0.5" alpha.over="0.3"
			distance="5" distance.over="15"
			blurX.over="15" blurY.over="15"
			inner.down="true"
		/>
	</s:filters>
	
	<s:Rect left="0" right="0" top="0" bottom="0" radiusX="5" radiusY="5">
		<s:fill>
			<mx:LinearGradient rotation="90">
				<mx:entries>
					<mx:GradientEntry color="#0a5c00" ratio="0.00"/>
					<mx:GradientEntry color="#84a381" ratio="0.50" ratio.over="0.25"/>
					<mx:GradientEntry color="#0a5c00" ratio="0.80"/>
				</mx:entries>
			</mx:LinearGradient>
		</s:fill>
	</s:Rect>
	
	<s:SimpleText id="labelElement" color="#ffffff"
		horizontalCenter="0" verticalCenter="0"
     	left="10" right="10" top="5" bottom="5"
     />	
	
	<s:layout>
		<s:BasicLayout/>
	</s:layout>
</s:Skin>

 

아래는 위 Skin을 사용한 소스이다.

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
	xmlns:fx="http://ns.adobe.com/mxml/2009" 
	xmlns:s="library://ns.adobe.com/flex/spark" 
	xmlns:mx="library://ns.adobe.com/flex/halo" 
	minWidth="500" minHeight="400"
	>
	<s:Button label="확인" skinClass="com.jidolstar.skins.MyButtonSkin"/>
</s:Application>

 

코딩하면서 느끼는 것이지만 Flex 4는 Flex 3하고 너무 다르다. ㅎㅎ  

스킨 부분에 있어서 Flex 3에서는 ProgrammaticSkin을 기반으로 Skin을 ActionScript 코드로 만들었는데 Flex 4부터는 MXML로 만들 수 있도록 했다. 이 부분이 가장 크게 달라진거다.

 

위의 Skin 코드를 살펴보면 몇가지 재미있는 점을 발견할 수 있다. 살펴보자.

 

먼저 HostComponent 메타 데이타를 볼 수 있다. Flex 4에서 나온 새로운 메타 데이타이다. 이것은 이 스킨이 어떤 컴포넌트가 Host인가 명시적으로 지칭해주는 역할을 한다. Button은 ButtonBase를 확장해서 만들었고 ButtonBase는 SkinnableComponent를 확장해서 만들어졌는데 HostComponent가 쓰이는 부분은 SkinnableComponent인 듯 보인다. 아래는 SkinnableComponent내에 정의된 attachSkin() 메소드이다. 이것은 createChildren() 혹은 commitProperties()가 호출될때 이 메소드가 호출되는데 skinClass 스타일이 바뀔 때 Skin을 붙여주는 역할을 담당한다.

 

    /**
     *  Create the skin for the component. 
     *  You do not call this method directly. 
     *  Flex calls it automatically when it calls createChildren() or  
     *  the UIComponent.commitProperties() method.
     *  Typically, a subclass of SkinnableComponent does not override this method.
     * 
     *  

This method instantiates the skin for the component, * adds the skin as a child of the component, and * resolves all part associations for the skin

* * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ protected function attachSkin():void { // Factory var skinClassFactory:IFactory = getStyle("skinFactory") as IFactory; if (skinClassFactory) setSkin( skinClassFactory.newInstance() as Skin ); // Class if (!skin) { var skinClass:Class = getStyle("skinClass") as Class; if (skinClass) setSkin( new skinClass() ); } if (skin) { skin.owner = this; // As a convenience if someone has declared hostComponent // we assign a reference to ourselves. If the hostComponent // property exists as a direct result of utilizing [HostComponent] // metadata it will be strongly typed. We need to do more work // here and only assign if the type exactly matches our component // type. if ("hostComponent" in skin) { try { Object(skin).hostComponent = this; } catch (err:Error) {} } // the skin's styles should be the same as the components skin.styleName = this; super.addChild(skin); skin.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, skin_propertyChangeHandler); } else { throw(new Error(resourceManager.getString("components", "skinNotFound", [this]))); } findSkinParts(); invalidateSkinState(); }

위 코드에 보면 hostComponent 부분이 보이는데 바로 HostComponent 메타데이터와 관련이 있어 보인다. 아직 정확한 동작방식은 모르겠다.

 

주제를 바꿔서 맨 위 코드에 <s:state>가 존재하는 것을 볼 수 있다. 이것은 상태를 의미하는 것으로 이미 Button 자체에 up, down, over, up 상태가 메타 데이터 형태로 정의 되어 있다. . ButtonBase에 보면 아래와 같은 방식으로 4개의 상태를 나타내는 메타 데이터가 정의되어 있다.

/**
 *  Up State of the Button
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[SkinState("up")]

/**
 *  Over State of the Button
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[SkinState("over")]

/**
 *  Down State of the Button
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[SkinState("down")]

/**
 *  Disabled State of the Button
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[SkinState("disabled")]

public class ButtonBase extends SkinnableComponent implements IFocusManagerComponent
{
   ...
}

 

저 상태변화는 SkinnableComponent 클래스에서 알아서 처리하도록 되어 있다. Button의 스킨의 상태에 따른 변화의 동작방식을 이해하기 위해 SkinnableComponent를 분석해야한다. 뭐, 분석까지 아니더라도 SkinnableComponent를 활용하는 방법만 알면 될 것이다. SkinnableComponent는 UIComponent를 확장한 것이고 모든 Spark 계열의 컴포넌트는 SkinnableComponent를 확장한 형태이다. ColorPicker나 DateChooser와 같이 예전 Halo 계열의 컴포넌트는 SkinnableComponent를 확장하지 않았다.

 

<s:filters>는 말그대로 필터를 설정하는 것을 의미한다. 여기서는 DropShadowFilter를 사용했다. Flex 4에서 추가한 새로운 기능중에 각 속성에 state를 지정할 수 있다. DropShadowFilter를 사용할 때도 아래 처럼 속성에 이 기능을 적용했다.  

 

alpha="0.5" alpha.over="0.3"

 

DropShadowFilter를 사용한 부분 중에 alpha값을 위처럼 사용했다. 보통때는 alpha값이 0.5이지만 상태가 over이면 0.3을 사용하겠다는 것을 의미한다. alpha.over="0.3" 부분이 어떻게 ActionScript 로 바뀌는가 살펴보려면 컴파일 옵션에 -keep-generated-actionscript를 해보면 알 수 있다. 그럼 컴파일을 하면 src/generated 폴더가 생성된다. 그 안에 com.jidolstar.skins 패키지로 가보면 MyButtonSkin-generated.as 파일이 있는데 열어보면 alpha.over="0.3" 가 어떻게 바뀌는가 한눈에 알 수 있다. 아래 코드는 MyButtonSkin-generated.as의 일부분이다.

 

    /**
     * @private
     **/
    public function MyButtonSkin()
    {
        super();
        // our style settings

        // properties
        this.filters = [_MyButtonSkin_DropShadowFilter1_i()];
        this.layout = _MyButtonSkin_BasicLayout1_c();
        this.mxmlContent = [_MyButtonSkin_Rect1_c(), _MyButtonSkin_SimpleText1_i()];
        this.currentState = "up";


        // events
		states = [
		  new State ({
		    name: "up",
		    overrides: [
		    ]
		  })
		  ,
		  new State ({
		    name: "down",
		    overrides: [
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_DropShadowFilter1",
		        name: "inner",
		        value: true
		      })
		    ]
		  })
		  ,
		  new State ({
		    name: "over",
		    overrides: [
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_DropShadowFilter1",
		        name: "alpha",
		        value: 0.3
		      })
		      ,
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_DropShadowFilter1",
		        name: "distance",
		        value: 15
		      })
		      ,
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_DropShadowFilter1",
		        name: "blurX",
		        value: 15
		      })
		      ,
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_DropShadowFilter1",
		        name: "blurY",
		        value: 15
		      })
		      ,
		      new mx.states.SetProperty().initializeFromObject({
		        target: "_MyButtonSkin_GradientEntry2",
		        name: "ratio",
		        value: 0.25
		      })
		    ]
		  })
		  ,
		  new State ({
		    name: "disabled",
		    overrides: [
		    ]
		  })
		];
    }

private function _MyButtonSkin_DropShadowFilter1_i() : spark.filters.DropShadowFilter
{
	var temp : spark.filters.DropShadowFilter = new spark.filters.DropShadowFilter();
	temp.quality = 3;
	temp.alpha = 0.5;
	temp.distance = 5;
	_MyButtonSkin_DropShadowFilter1 = temp;
	return temp;
}

 

결국 alpha.over="0.3"는 State 객체를 만들어 각 상태에 따른 속성으로 지정해버리도록 만들어진다. currentState를 "up"으로 설정하고 상태가 바뀔 때마다 등록된 State를 실행하도록 되는 것이다. 이걸 보니깐 원리가 확실히 이해가 된다.

 

다시 돌아가서....

<s:Rect>과 <s:SimpleText>는 mxmlContent=[_MyButtonSkin_Rect1_c(), _MyButtonSkin_SimpleText1_i()] 의 형태로 추가 된다. mxmlContent도 Flex 4부터 추가된 속성인데 생소하기 짝이 없다. ㅎㅎ 좀 알아보기 위해 또 뒤져봤다.

 

//----------------------------------
//  mxmlContent
//----------------------------------

private var mxmlContentChanged:Boolean = false;
private var _mxmlContent:Array;

[ArrayElementType("mx.core.IVisualElement")]

/**
 *  The visual content children for this Group.
 *
 *  

The content items should only be IVisualItem objectss. * An mxmlContent Array should not be shared between multiple * Group containers because visual elements can only live in one container * at a time.

* *

If the content is an Array, do not modify the Array * directly. Use the methods defined by Group class instead.

* * @default null * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get mxmlContent():Array { if (_mxmlContent) return _mxmlContent.concat(); else return null; } /** * @private */ public function set mxmlContent(value:Array):void { if (createChildrenCalled) { setMXMLContent(value); } else { mxmlContentChanged = true; _mxmlContent = value; // we will validate this in createChildren(); } } /** * @private * Adds the elements in mxmlContent to the Group. * Flex calls this method automatically; you do not call it directly. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ private function setMXMLContent(value:Array):void { var i:int; // if there's old content and it's different than what // we're trying to set it to, then let's remove all the old // elements first. if (_mxmlContent != null && _mxmlContent != value) { for (i = _mxmlContent.length - 1; i >= 0; i--) { elementRemoved(_mxmlContent[i], i); } } _mxmlContent = (value) ? value.concat() : null; // defensive copy if (_mxmlContent != null) { var n:int = _mxmlContent.length; for (i = 0; i < n; i++) { var elt:IVisualElement = _mxmlContent[i]; // A common mistake is to bind the viewport property of an Scroller // to a group that was defined in the MXML file with a different parent if (elt.parent && (elt.parent != this)) throw new Error(resourceManager.getString("components", "mxmlElementNoMultipleParents", [elt])); elementAdded(elt, i); } } }

 

위 코드는 Group 클래스이다. mxmlContent는 Skin 클래스의 부모 클래스인 Group에 구현되어 있는 속성인 것이다. mxmlContent에 값을 설정하면 setMXMLContent() 함수가 호출되어 기존의 MXML 추가된 Element들을 지우고 새로운 Element인 Rect과 SimpleText를 추가한다. 또한 IVisibelElement인 컴포넌트만 자식으로 추가하도록 되어 있고 다른 부모를 가지는 컴포넌트인 경우에 예외처리도 한다. 결국 mxmlContent은 Group에서 사용된 MXML형태의 비주얼 컴포넌트를 Flex 컴파일러가 AS3로 추가해주기 위해 만들어진 것이다.

 

<s:Application> 부분에 버튼 추가한 부분은 어떻게 변해 있을까? 살펴보면 아래 처럼 되어 있다.

private function _sparkskin_Button1_c() : spark.components.Button
{
	var temp : spark.components.Button = new spark.components.Button();
	temp.label = "확인";
	temp.setStyle("skinClass", com.jidolstar.skins.MyButtonSkin);
	if (!temp.document) temp.document = this;
	return temp;
}

skinClass가 원래 Style속성이다. SkinnableComponent를 보면 [Style(name="skinClass", type="Class")]로 정의 되어 있다. 이는 validateSkinChange() 함수에서 붙여주게 된다.

 

/**
 *  @private
 */
private function validateSkinChange():void
{
    // If our new skin Class happens to match our existing skin Class there is no
    // reason to fully unload then reload our skin.  
    var skipReload:Boolean = false;
    
    if (_skin)
    {
        var factory:Object = getStyle("skinFactory");
        var newSkinClass:Class;
        
        if (factory)
            newSkinClass = (factory is ClassFactory) ? ClassFactory(factory).generator : null;
        else
            newSkinClass = getStyle("skinClass");
            
        skipReload = newSkinClass && 
            getQualifiedClassName(newSkinClass) == getQualifiedClassName(_skin);
    }
    
    if (!skipReload)
    {
        if (skin)
            detachSkin();
        attachSkin();
    }
}

 

내가 한가지 흥미를 느꼈던 것은 바로 <s:SimpleText> 부분이였다. Flex 4의 Button은 Label의 컴포넌트를 바꿀 수 없었는데 Flex 4에서는 스킨 기능을 이용해 Text엔진을 바꿀 수 있다. 가령 <s:SimpleText> 대신 <s:RichText>로 바꿔보길 바란다. 잘 된다. 이는 TextGraphicElement를 확장한 SimpleText와 RichText만 가능하다. 만약 TextArea와 같은 것을 사용하면 아래와 같은 에러가 나오게 된다.

 

TypeError: Error #1034: 유형 강제 변환에 실패했습니다. spark.components::TextArea@70c36d1을(를) spark.primitives.supportClasses.TextGraphicElement(으)로 변환할 수 없습니다.

 

이런 식의 사용은 Spark 컴포넌트 전체에서 사용할 수 있다. 참 좋은 방법이다.

 

 

생각하기

 

Flex 4는 Flex 3 처럼 무리하게 ActionScript 3.0까지 분석할 필요까지 느끼게 해주지 않도록 하는 것이 컨셉인 것 같다. 하지만 내가 좀 독특한 건가 예전 버릇을 버리지 못해 어찌 돌아가는지 알고 싶어서 Flex 4 SDK를 훑어보게 되었다. 하지만 이렇게 저렇게 분석하면서 살펴봤지만 아직도 모르는게 산적해있다. 먼저 사용하는 법부터 좀 공부해야겠다. ㅎㅎ

 

관련글

Getting started with Spark skins

Creating Spark Skins

The Spark Group and Spark SkinnableContainer containers

 

 

글쓴이 : 지돌스타(http://blog.jidolstar.com/558)

 

예전부터 Flex4 프로젝트의 일환인 Gumbo를 다운로드를 받았지만 쓸 기회가 없어서 안쓰다가 Flash Player 10에서 3D 회전 예제가 있어서 한번 해봤다.

Flex Builder 3에서 작업을 하기 위해 수행해야할 일은 다음과 같다.

1. Gumbo 최신버전을 다운받는다. [다운로드 받으러가기]

2. 다운로드 받는 Flex 4 SDK를 Flex Builder 설치폴더안에 sdks 폴더에 압축하여 풀어준다.

3. Flex Builder 3를 실행해서 메뉴에 Windows->Preperences...에 들어가면 창이 뜬다. 창 왼쪽에 Flex->Installed Flex SDKs를 선택한 다음 아까 압축을 푼 SDK폴더를 등록한다.

4. File->New->ActionScript Project를 선택하면 창이 뜬다. 창 아래부분에 Use a specific SDK를 선택한다음 Flex 4를 선택하고 프로젝트 명을 CubeRotationExample로 프로젝트를 만든다.

5. 아래 소스를 복사해서 메인 소스에 덮어쓴다.

 

package{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
 
	public class CubeRotationExample extends Sprite {
		
		private static const EDGE	:Number = 40;		//edge length
		private var mtxWorld		:Matrix3D;			//world transform matrix
		private var vCube			:Vector.<Number>;	//cube points
		private var vFlatCube		:Vector.<Number>;	//projected cube points
		private var vUVT			:Vector.<Number>;	//uvt data
		private var vIndicies		:Vector.<int>;		//triangle indicies
		private var sprCube			:Sprite;			//canvas object
		
		public function CubeRotationExample(){
			// setup and initialize
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.quality = StageQuality.BEST;			
			
			mtxWorld = new Matrix3D();
			vCube = Vector.<Number>([	EDGE,EDGE,-EDGE,
				 						EDGE,-EDGE,-EDGE, 
										-EDGE,-EDGE,-EDGE,
										-EDGE,EDGE,-EDGE, 
										EDGE,EDGE,EDGE,
										EDGE,-EDGE,EDGE,
										-EDGE,-EDGE,EDGE,
										-EDGE,EDGE,EDGE
										]);
			vFlatCube = new Vector.<Number>(16);
			vUVT = new Vector.<Number>(24);
			vIndicies = Vector.<int>([0,1,2, 2,3,0, 4,7,6, 6,5,4, 0,4,5, 5,1,0, 1,5,6, 6,2,1, 2,6,7, 7,3,2, 4,0,3, 3,7,4]);
			
			sprCube = new Sprite();
			addChild(sprCube);

			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(eo:Event):void {
			// center the cube
			sprCube.x = stage.stageWidth/2;
			sprCube.y = stage.stageHeight/2;
			
			// rotate the transform matrix
			mtxWorld.appendRotation(2, new Vector3D(0,1,0));
			mtxWorld.appendRotation(2, new Vector3D(0,0,1));
			mtxWorld.appendRotation(2, new Vector3D(1,0,0));
			
			// project 3D data to 2D plane
			Utils3D.projectVectors(mtxWorld, vCube, vFlatCube, vUVT);
			
			// draw the cube using cube data
			sprCube.graphics.clear();
			sprCube.graphics.beginFill(0xFF00FF);
			sprCube.graphics.lineStyle(1,0xFF0000,1);
			sprCube.graphics.drawTriangles(vFlatCube, vIndicies, null, TriangleCulling.POSITIVE);
			sprCube.graphics.endFill();
		}
	} 
}

 

6. 저장하면 에러가 날거다. Flash Player 10에서 작동하므로 그에 따른 설정을 해주어야 한다. 메뉴에서 Project->Properties 로 들어가면 창이 뜬다. 왼쪽메뉴에 ActionScript Compiler를 선택하고 오른쪽 아래 Require Flash Player version을 10.0.0으로 맞춰준다.

7. 실행한다.(단 Flash Player 10이 설치되어 있어야 한다.)


[실행화면]


다시한번 언급하지만 Flash Player 10 환경에서만 된다.

위의 소스를 보면 예전 ActionScript 3.0에서 볼 수 없었던 것들이 보인다.
Vector, Matrix3D, Util3D등이다. Papervision3D와 같은 것을 쓰지않아도 쉽게 네이티브 코드로 3D를 구현할 수 있게 한 Flash Player 10. 아직 다양한 표현을 위한 많은 API를 가지고 있지 않지만 더욱 발전될 가능성이 크다고 생각한다. 기대해보겠다.

[소스출처]
http://dispatchevent.org/calebjohnston/flash-player-10-3d-example/

글쓴이 : 지돌스타(http://blog.jidolstar.com/421)

+ Recent posts