Warning: opendir(/var/www/html/wp-content/mu-plugins): Failed to open directory: Permission denied in /var/www/html/wp-includes/load.php on line 981 Flash – sewonist.com https://sewonist.com sewonist = sewon + artist Fri, 10 Apr 2020 03:43:06 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://sewonist.com/wp-content/uploads/2015/08/cropped-sewonist-32x32.png Flash – sewonist.com https://sewonist.com 32 32 ProcessIndicator for Starling https://sewonist.com/processindicator-for-starling/ https://sewonist.com/processindicator-for-starling/#respond Tue, 12 Mar 2013 05:25:41 +0000 https://sewonist.com/?p=3600 Read More »ProcessIndicator for Starling]]> 아이폰이 널리 사용되어지면서 함께 많이 사용하게 된 UI 중 하나가 ProcessIndicator 입니다. iOS 클래스 명으로는 UIActivityIndicatorView 가 바로 그것이죠.

이전에 사용하던 이 ProcessIndicator  를 Starling 용으로 만들어 보았습니다.  스탈링의 DisplayObject 와 기존 DisplayObject 는 거의 대동소이하므로 아무생각 없이 패키지만 스탈링으로 바꾸었습니다. 결과는…

잘 나오는데.. 어라 뭔가 이상하다~~~ 보통 이런 인디케이터의 경우 슬라이스의 각만큼 회전을 해야 합니다. 그런데 이 회전을 시키는 부분이 기존의 플래시와 스탈링이 약간 다릅니다. 기존의 rotation 은 360 즉 일반적인 각도로 회전하지만 스탈링의 rotation 은 라디안 값으로 회전합니다. 간단한거지만 아는데 반나절 걸렸음;;;; 그래서 원래 소스를 아래와 같이 변경 해야 합니다.

[as3]
rotation = rotation + (360 / slices) % 360; // degree 로 계산
rotation = deg2rad(( rad2deg(rotation) + (360 / slices)) % 360); // radian 으로 계산
[/as3]

어떤분들은 degree 와 radian 을 왔다갔다 할 필요가 있는지 궁굼해 하 실 수 있는데. 네, 없습니다. 처음부터 기준을 radian 으로 나눠 주면 저렇게 복잡하게 할 필요는 없습니다. 다만 spinnerSkin 을 플래시의 Shape 으로 만들기 때문에 이때는 degree 기준으로 슬라이스를 만들어야 합니다. 결국 조삼모사~ (제가 바꾸기 귀잖아서 그런거 절대 아님.)

전체 소스는 아래와 같습니다.

[as3]
package
{
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;

import starling.display.DisplayObjectContainer;
import starling.display.Image;
import starling.events.Event;
import starling.textures.Texture;
import starling.utils.deg2rad;
import starling.utils.rad2deg;

public class ProcessIndicator extends DisplayObjectContainer
{
private var _spinnerSkin:Image;

private var timer:Timer;
private var slices:int;
private var radius:int;
private var _image:Image;

public function ProcessIndicator(slices:int = 12, radius:int = 6)
{
super();
this.slices = slices;
this.radius = radius;

spinnerSkin = makeSpinner();

addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}

private function onAddedToStage(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
timer = new Timer(1000/30);
timer.addEventListener(TimerEvent.TIMER, onTimer, false, 0, true);
timer.start();
}

private function onRemovedFromStage(event:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
timer.reset();
timer.removeEventListener(TimerEvent.TIMER, onTimer);
timer = null;
}

private function onTimer(event:TimerEvent):void
{
spinnerSkin.rotation = deg2rad(( rad2deg(spinnerSkin.rotation) + (360 / slices)) % 360);
}

private function makeSpinner():Image
{
var i:int = slices;
var degrees:int = 360 / slices;
var slider:flash.display.Sprite = new flash.display.Sprite;
while (i–)
{
var slice:Shape = getSlice();
slice.alpha = Math.max(0.2, 1 – (0.1 * i));
var radianAngle:Number = (degrees * i) * Math.PI / 180;
slice.rotation = -degrees * i;
slice.x = (Math.sin(radianAngle) * radius)+radius*2;
slice.y = (Math.cos(radianAngle) * radius)+radius*2;

slider.addChild(slice);
}

var bitamp:BitmapData = new BitmapData(slider.width, slider.height, true, 0);
bitamp.draw(slider);

var texture:Texture = Texture.fromBitmapData(bitamp, false, false);
var spinner:Image = new Image(texture);
spinner.pivotX = spinner.width >> 1;
spinner.pivotY = spinner.height >> 1;

return spinner;
}

private function getSlice():Shape
{
var slice:Shape = new Shape();
slice.graphics.beginFill(0x222222);
slice.graphics.drawRoundRect(-1, 0, 2, radius, radius*2, radius*2);
slice.graphics.endFill();

return slice;
}

//=====================================================================
//
// getter & setter
//
//=====================================================================

public function get spinnerSkin():Image
{
return _spinnerSkin;
}

public function set spinnerSkin(value:Image):void
{
if(_spinnerSkin == value)
{
return;
}

if(_spinnerSkin)
{
removeChild(_spinnerSkin);
}

_spinnerSkin = value;

if(this._spinnerSkin && this._spinnerSkin.parent != this)
{
_spinnerSkin.visible = true;
_spinnerSkin.touchable = false;
addChild(_spinnerSkin);
}
}

}
}
[/as3]

결과물

원래 이번 포스팅의 목적은 radian 과  degree 의 집중분석이었으나 연속 포스팅으로 텐션이 떨어져서 소스 공유 정도로 마무리 하겠습니다.

샘플 소스

[button url=”https://sewonist.com/wp-content/uploads/2013/03/ProcessIndicator.zip”]Download ProcessIndicator.zip[/button]

]]>
https://sewonist.com/processindicator-for-starling/feed/ 0
SeeU dance in Away3D https://sewonist.com/seeu-dance-in-away3d/ https://sewonist.com/seeu-dance-in-away3d/#respond Tue, 16 Oct 2012 07:23:26 +0000 https://sewonist.com/?p=3252 Read More »SeeU dance in Away3D]]> 필 받은 김에 응용편 까지 계속 달려 보도록 하겠습니다. 한국판 보컬로이드인 SeeU 데이터를 Away3D로 가져와 보도록 하겠습니다. 같은 데이터를 Unity3D 로 가져온 Future of Flash 와 비교해서 보시는 것도 재미있을 것 같네요.

위의 최종결과물은 마우스 드래그로 회전, 휠 줌 인/아웃 그리고 버튼 클릭으로 에니메이션을 고를 수 있습니다.

준비물

MikuMikuDance

들어가기에 앞서 미쿠미쿠댄스에 대해서 간단히 알아보겠습니다. 아시는 분들은 아시겠지만 미쿠미쿠댄스는 일본 야마하의 보컬로이드 캐릭터인 하츠네 미쿠를 춤추게 만들어 보겠다는 일본의 한 대인배께서 만들어낸 프로그램입니다. 기본적으로 캐릭터 모델링 데이터를 가지고 있는 .pmd 파일과 에니메이션 데이터를 가지고 있는 .vmd 파일로 나뉘어져 있습니다. 이는 md5 포멧과도 유사하네요. .pmd 캐릭터의 주요 본은 기본적으로 동일하기 때문에 어떤 .pmd 파일에도 .vmd 를 이용하여 춤추게 만들 수 있습니다.

실제 미쿠미쿠댄스 프로그램은 매우 디테일한 설정까지 가능하게 되어있습니다. 심지어 간단한 표정 변화도 표현 할 수 있습니다. 거기에 가장 부러운 기능인 물리 시물레이션이 되서 아주 자연스러운 에니메이션을 만들 수 있습니다. 아직 아쉽게도 Away3D 에서는 동적인 시물레이션은 어렵습니다. 여튼 모르시는 분이 보면 오덕오덕 하다 하실지 모르겠지만 모든 일은 이 덕력이 있기에 가능 하지 않았나 싶습니다. 그런 의미에서 저는 아직 덕력이 많이 부족하네요ㅋㅋ

플러그인 설치

위의 준비물에 있는 두 플러그인을 받아서 압축을 풀고 아래의 그림과 같이 블렌더 addons 폴더에 넣습니다.

MeshIO 는 .pmd 파일을 import 하기 위한 애드온이고 io_import_vmd 는 이름처럼 .vmd 파일을 import 하기 위한 애드온입니다. 여기서 일단 주의하실 점은 원본 MeshIO(http://sourceforge.jp/projects/meshio/) 의 경우 import 가 제대로 안되었습니다. 정확한 원인은 모르겠으나 아마 언어셋 문제가 아닌가 추측 중입니다. 제가 첨부한 파일은 서양커뮤니티에서 같은 이유로 안되는걸 수정한 버전입니다.

그리고 io_import_vmd 를 사용하기 위해서는 반드시 MeshIO 폴더 이름을 meshio 로 해야 합니다.

위의 그림과 같이 환경설정에서 애드온을 활성화 해주면 설치 완료 입니다. 그럼 이제 인터넷 어디선가 .pmd 파일과 .vmd 파일을 구해 import 하면 됩니다. 아쉽게도 제가 사용한 파일은 모두 출처와 저적권에 문제가 있는 관계로 소스를 공유 못하는 점 양해 바랍니다. 일본쪽에서 클레임 걸면 글 내려야 할지도… 여튼 .pmd 와 .vmd 를 모두 정상적으로 import 하면 아래와 같은 화면이 나옵니다.

별 문제가 없어 보이지만 실제로 자세히 보면 아래와 같이 모델링이 깨져있는 걸 확인 할 수 있습니다.

아마도 mesh 의 중심과 bone 의 중심점 등이 달라서 생기는 현상 같은데 정확한 이유는 모르겠습니다. 여튼 다행인지는 모르겠으나 이대로 md5 로 추출 하여도 거의 대부분 정상적으로 플레이가 됩니다.

이 다음부터는 How to make MD5 for Away3D in Blender? 에서 본대로 md5 로 추출하고 Away3D 에서 가져오면 됩니다.

마치며

맨위의 결과물을 보면 로딩이 상당히 오래 걸리는 것을 알 수 있습니다. swf 크기만 13M 이고 파일로드 이후에 md5 파싱에도 상당한 시간이 걸립니다. 저번에도 언급했지만 md5 포멧은 사실 이러한 model 데이터에는 사용하기 적합하지 않은 포멧입니다. 사용된 .md5mesh 가 8M Full Dance 용 .md5anim 가 31M 입니다. 그나마 플래시에 embed 해서 용량이 줄어들었습니다. 원본 파일인 .pmd 가 2.3M 이고 .vmd 가 970K 인거에 비교하면 엄청난 손실이 아닐 수 없습니다. 즉 md5 포멧은 가능한 적은 폴리곤으로 이루어진 모델링 데이터와 여러개의 에니메이션을 컨트롤 해야 할 때 사용해야 할 것 같습니다.

참고

  1. http://nikq.org/archives/303
  2. http://www.oogtech.org/content/tag/import-from-mmd-to-blender/
]]>
https://sewonist.com/seeu-dance-in-away3d/feed/ 0
ANE 빌드와 테스트 하기 https://sewonist.com/ane-%eb%b9%8c%eb%93%9c%ec%99%80-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ed%95%98%ea%b8%b0/ https://sewonist.com/ane-%eb%b9%8c%eb%93%9c%ec%99%80-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ed%95%98%ea%b8%b0/#comments Wed, 22 Aug 2012 02:00:43 +0000 https://sewonist.com/?p=3001 Read More »ANE 빌드와 테스트 하기]]> 연재순서
  1. ANE 살펴보기
  2. iOS용 ANE 라이브러리 만들기
  3. Android용 ANE 라이브러리 만들기
  4. 연결 SWC 만들기
  5. ANE 빌드와 테스트 하기

작업환경

  • Mac OS 10.7.4
  • Flex SDK 4.6.0 for AIR3.3
  • Flash Builder 4.6

소스 다운로드

[button url=’https://github.com/sewonist/ScreenWakeUp’ target=’_blank’ size=’large’]Sources in GitHub[/button]

시작점 만들기

드디어 연재 마지막 시간입니다. 앞시간에 만든 파일들을 모두 모아 ane 를 만들어 보도록 하겠습니다. 사실 ane 빌드 자체는 한줄 명령어로 끝날 정도로 단순하지만 실제로 ane 를 만들려고 시도 할 때 많이 어려워하는 부분입니다. 그중 가장 큰이유는 GUI에 익숙해 있는 개발자가 커맨드라인을 이용해서 빌드 해야 하기 때문입니다. 그래서 많은 개발자들이 build.bat 이나 build.xml 을 이용해서 빌드를 하지만 커맨드라인을 수정해야 한다는 점은 변함이 없습니다. 그러므로 이번 기회에 adt를 이용한 빌드를 익혀 두는 것도 좋을 것 같습니다.

build 디렉토리

위의 디렉토리에 지금까지 만든 라이브러리와 SWC 를 모아 두었습니다. libScreenWakeUp.a 는 iOS용 라이브러리 에서 SecreenWakeUp.jar 는 Android용 라이브러리에서 마지막으로 ScreenWakeUp.swc는 연결 SWC 입니다. 그리고 나머지 2개의 xml 지금부터 차례대로 알아보겠습니다.

extension.xml

[xml]
<extension xmlns="http://ns.adobe.com/air/extension/3.1">
<id>it.ane.ScreenWakeUp</id>
<versionNumber>1.1</versionNumber>
<platforms>
<platform name="iPhone-ARM">
<applicationDeployment>
<nativeLibrary>libScreenWakeUp.a</nativeLibrary>
<initializer>ExtInitializer</initializer>
<finalizer>ExtFinalizer</finalizer>
</applicationDeployment>
</platform>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>ScreenWakeUp.jar</nativeLibrary>
<initializer>it.ane.screenwakeup.ScreenWakeUpExtension</initializer>
</applicationDeployment>
</platform>
</platforms>
</extension>
[/xml]

xml 의 정확한 구조와 명세는 다음의 링크에서 확인 할 수 있습니다. Native extension descriptor files 여기서는 중요한 몇가지만 설명하겠습니다.

id
ANE의 고유 id 입니다. 이 아이디는 연결 SWC 가 context를 만들 때 사용하는 id와 동일합니다.

platform
각 플렛폼을 정의하는 노드 입니다. 플렛폼에 사용 할 수 있는 name 속성은 다음과 같습니다.

  • Android-ARM for Android devices.
  • default
  • iPhone-ARM for iOS devices.
  • iPhone-x86 for the iOS Simulator.
  • MacOS-x86 for Mac OS X devices.
  • QNX-ARM for Blackberry Tablet OS devices.
  • Windows-x86 for Windows devices.

nativeLibrary
해당 플렛폼에서 사용한 라이브러리 파일명입니다.

initializer
미리 정의된 initializer 함수 또는 클래스명입니다.

AIR런타임은 위와 같이 extension.xml 에 정의된 값을 토대로 context 를 생성하는 것 입니다.

build.xml

[xml]
<?xml version="1.0" encoding="UTF-8"?>
<project name="Air Native Extension Build Scripts" default="package">

<property name="name" value="ScreenWakeUp"/>
<property name="sdk.home" value="/Applications/Adobe Flash Builder 4.6/sdks/4.6.0_AIR3.3"/>
<property name="bin.ext" value=""/>

<target name="package" description="Create the extension package">
<exec executable="${sdk.home}/bin/adt${bin.ext}" failonerror="true" dir="./">
<arg value="-package"/>
<arg value="-target"/>
<arg value="ane"/>
<arg value="${name}.ane"/>
<arg value="./extension.xml"/>
<arg line="-swc ${name}.swc"/>
<arg line="-platform iPhone-ARM library.swf libScreenWakeUp.a"/>
<arg line="-platform Android-ARM library.swf ScreenWakeUp.jar"/>
</exec>
</target>
</project>
[/xml]

build.xml 은 빌드 자동화를 위한 ANT 설정 파일입니다. ANT 에 대해서는 위키에서 간단히 알아볼 수 있습니다. 예시로든 build.xml 은 단순히 ane 빌드만 하고 있으므로 딱히 ant 를 사용 할 필요 없어 보이지만 사실은 그렇지 않습니다. ane 개발은 네이티브 라이브러리, 연결 SWC 그리고 테스트 애플리케이션 까지 빌드가 되야 비로서 테스트가 가능합니다. 그런데 이런 일련의 과정을 일일이 빌드하려면 쓸데 없이 낭비되는 시간도 많을 뿐더러 불편하기 그지 없습니다. 그래서 보통 build.xml 에는 각 네이티브 라이브러리의 빌드, 연결 SWC의 빌드, 파일의 복사 및 압축 해제, ane 빌드 등이 모두 포함 되어 있습니다.

여기서 인자로 들어가는 -platform 은 extension.xml 에 정의된 platform 과 동일 해야 합니다. 그리고 시작점에서 보았던 폴더에 없던 파일이 보이는 바로 library.swf 입니다. 이는 ScreenWakeUp.swc 의 library.swf 입니다. ScreenWakeUp.swc 를 압축해제하고 같은 폴더에 library.swf 를 넣어두면 됩니다.

이제 모든 파일이 준비 되었다면 빌드를 해보겠습니다.

빌드는 개미가~

2초만에 빌드에 성공하였습니다. ㅎㅎㅎ 그리고 ScreenWakeUp.ane가 생성 된 것도 확인 할 수 있습니다. 이렇게 우리가 필요한 ane 제작이 완료 되었습니다.

테스트 하기

그럼 제작한 ane가 잘 작동하는지 테스트 앱을 만들어 보겠습니다.

새로운 모바일 프로젝트 생성
프로젝트명 이름 입력

프로젝트명을 입력하고 SDK는 AIR3.3 이상으로 합니다.

플렛폼 선택

ScreenWakeUp.ane 는 iOS 와 Android 는 지원하니 두 플렛폼만 선택 합니다.

ScreenWakeUp.ane 를 복사

build 폴더에서 빌드된 ScreenWakeUp.ane 를 프로젝트 폴더에 복사합니다.

Libraray path 설정

연결 SWC 를 이용하기 위해 Library path 를 설정합니다. ane는 ane파일안에 연결 SWC 를 포함하고 있으므로 따로 SWC 를 넣을 필요 없이 ane 파일 하나로 같이 사용 할 수 있습니다.

ANE 파일 추가

Native Extensions 탭에서 ANE 파일을 추가합니다. ane의 각종 정보를 확인 할 수 있습니다.

[as3]
package
{
import com.bit101.components.Label;
import com.bit101.components.PushButton;

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;

import it.ane.ScreenWakeUp;

public class ScreenWakeUpTester extends Sprite
{
private var _buttonOn:PushButton;
private var _buttonOff:PushButton;
private var _status:Label;
private var _screenWakeUp:ScreenWakeUp;
private var _isSupported:Boolean;

public function ScreenWakeUpTester()
{
super();

stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

_buttonOn = new PushButton(this, 100, 20, "ScreenWakeUp ON", onClick);
_buttonOff = new PushButton(this, 100, 50, "ScreenWakeUp OFF", onClick);
_status = new Label(this, 100, 80, "status : OFF");

_screenWakeUp = new ScreenWakeUp;
_isSupported = _screenWakeUp.isSupported;

}

protected function onClick(event:MouseEvent):void
{
if(event.currentTarget == _buttonOn){
if(_isSupported){
_screenWakeUp.lock(true);
_status.text = "status : ON";
}
} else if (event.currentTarget == _buttonOff) {
if(_isSupported){
_screenWakeUp.lock(false);
_status.text = "status : OFF";
}
}
}
}
}
[/as3]

위와 같인 간단히 테스트 코드를 작성 합니다.

[as3]
_screenWakeUp.lock(true); //화면 잠금 설정

_screenWakeUp.lock(false); //화면 잠금 해제
[/as3]

ScreenWakeUp.ane 의 연결 SWC 인스턴스인 _screenWakeUp 을 이용하여 화면 잠금 해제를 할 수 있습니다. 마지막으로 아래와 같이 ane 파일을 패키지에 포함 시켜고 테스트 앱 프로젝트를 빌드합니다.

ANE 를 패키지에 포함

정리

총 5회에 걸쳐 ANE에 대해서 알아보고 iOS, Android 각 플렛폼용 라이브러리와 연결 SWC 를 만들어 보았습니다. 그리고 ANE를 빌드하여 테스트앱을 통해 정상 작동하는지도 살펴보았습니다. 사실 지금까지는 제가 미리 테스트한 샘플을 가지고 예제로 보여 드렸기 때문에 별 문제 없이 모든게 진행 되었습니다. 하지만 실제 개발에서는 지금 부터가 문제 입니다. 막상 ANE 개발을 해보면 여기까지 와서 테스트를 하면 안되는 경우가 상당히 많기 때문입니다. ANE의 태생적인 단점으로 여러 레이어층을 가진다는게 문제 입니다. 정확히 어느 부분에서 문제가 발생 했는데 파악하기가 어렵습니다. 디버그도 쉽지 않구요. 이를 해결 하기 위해서는 최대한 초기에 계획을 잘 세우고 중간중간 가능한 많은 테스트슈트를 만들어 테스트를 하면 진행 하여야 하겠습니다.

이번 연재에 사용된 모든 소스는 아래의 Github에 공유 되어 있으니 소스를 보시고 테스트해보시기 바랍니다. 긴글 끝까지 읽어 주셔서 대단히 감사합니다.^^

]]>
https://sewonist.com/ane-%eb%b9%8c%eb%93%9c%ec%99%80-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ed%95%98%ea%b8%b0/feed/ 10
연결 SWC 만들기 https://sewonist.com/%ec%97%b0%ea%b2%b0-swc-%eb%a7%8c%eb%93%a4%ea%b8%b0/ https://sewonist.com/%ec%97%b0%ea%b2%b0-swc-%eb%a7%8c%eb%93%a4%ea%b8%b0/#respond Sun, 19 Aug 2012 23:30:54 +0000 https://sewonist.com/?p=2986 Read More »연결 SWC 만들기]]> 연재순서
  1. ANE 살펴보기
  2. iOS용 ANE 라이브러리 만들기
  3. Android용 ANE 라이브러리 만들기
  4. 연결 SWC 만들기
  5. ANE 빌드와 테스트 하기

작업환경

  • Mac OS 10.7.4
  • Flex SDK 4.6.0 for AIR3.3
  • Flash Builder 4.6

소스 다운로드

[button url=’https://github.com/sewonist/ScreenWakeUp’ target=’_blank’ size=’large’]Sources in GitHub[/button]

연결 SWC

제가 연결 SWC 라고 부르는 이 부분의 호칭이 참 모호합니다. 다른 외국문서는 대부분 ActionScript3 Code 로 하는 것 같은데 그건 그냥 언어 이름이라서 헷갈릴 소지가 있습니다. 일단 앞으로 공통된 호칭이 나오기 전까지 저는 그냥 연결 SWC 라고 부르겠습니다. 제가 이 파트를 연결 SWC 라고 부르는 이유는 이 SWC가 네이티브 라이브러리와 앞으로 개발할 다른 플래시들과의 연결점이 되어주기 때문입니다.

연결구조

위의 그림은 연결 SWC 가 실제로 어떻게 작동하는 지를 보여주고 있습니다. 연결 SWC는 extension.xml 을 참조하여 각 OS에 맞는 context 를 생성합니다. 그리고 이 context 를 통해 네이티브 라이브러리와 통신하게 됩니다.

시작점 만들기

프로젝트 생성

새로운 Flex Library Project 를 생성합니다.

프로젝트 이름 입력

프로젝트 이름을 입력하고 Flex SDK 는 AIR3.3 이상이 적용된 버전을 선택합니다.

클래스 생성

이번 ScreenWakeUp ANE에서는 이벤트를 발생 하지 않지만 대부분의 ANE가 연결 SWC에서 이벤트를 사용하고 있습니다. 이를 대비해서 EventDispatcher를 확장했습니다. ANE 에서의 이벤트는 비동기로 이루어지기 때문에 약간의 처리가 필요합니다. ANE 에서의 이벤트 처리에 대해서 다음에 알아보도록 하고 이번에는 일단 지나가도록 하겠습니다.

코드작성

[as3]
package it.ane
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.StatusEvent;
import flash.external.ExtensionContext;

public class ScreenWakeUp extends EventDispatcher
{
private static const EXTENSION_ID : String = "it.ane.ScreenWakeUp";

private var context:ExtensionContext;

public function ScreenWakeUp(target:IEventDispatcher=null)
{
super(target);

try{
context = ExtensionContext.createExtensionContext(EXTENSION_ID, null);
context.addEventListener(StatusEvent.STATUS, onStatusHandler);
}catch(e:Error){
trace(e.message, e.errorID);
}
}

protected function onStatusHandler(event:Event):void
{

}

public function get isSupported():Boolean{
var result:Boolean = context.call("isSupported");
return result;
}

public function lock($flag:Boolean):void
{
context.call("lock", $flag);
}

}
}
[/as3]

오~~~ 드디어 고향에 돌아왔습니다. 그동안 외계어를 보느라 고생 많았습니다. 이제 다시 안방으로 돌아왔습니다. 심지어 코드도 짧습니다. 특별히 설명이 없어도 다 이해할 수 있는 수준이지만 포스팅을 길게 하기 위해서 약간의 설명을 하겠습니다.^^

[as3]
private static const EXTENSION_ID : String = "it.ane.ScreenWakeUp";
[/as3]

EXTENSION_ID는 extension.xml 에 정의되어 있는 ANE의 id 입니다. 이 id를 통해서 ANE를 구별하고 context를 생성 합니다.

[as3]
context = ExtensionContext.createExtensionContext(EXTENSION_ID, null);
[/as3]

ExtensionContext 의 createExtensionContext 함수를 통해 실제 context를 생성 합니다. createExtensionContext 의 첫번째 인자는 extensionId 두번째 인자는 contextType 입니다. extensionId 를 참조하여 context를 생성하고 contextType을 인자로 넘겨 하나의 extension 에서 원하는 context를 생성 할 수 있게 합니다. 다만 보통은 단일 기능만 제공하므로 일반적으로 null을 넘기고 있습니다.

바로 이 시점에서 iOS의 경우 ExtInitializer를 통한 ContextInitializer 함수가 Android의 경우 ScreenWakeUpExtension 의 createContext 함수가 실행 되면서 context 가 생성 됩니다.

[as3]
public function lock($flag:Boolean):void
{
context.call("lock", $flag);
}
[/as3]

그리고 ExtensionContext 의 call(functionName:String, … args) 함수를 통해 네이티브 라이브러리의 함수를 실행하게 됩니다. functionName은 우리가 지난시간에 만든 각 라이브러리에서 함수이름으로 등록된 이름 입니다.

정리

이제 ANE 를 만들기 위한 거의 모든 준비가 되었습니다. 첫 시간 ANE 살펴보기에서 알아본 ANE 구조 처럼 ANE는 네이티브 라이브러리 + 연결 SWC + extension.xml 의 압축파일입니다. 네이티브 라이브러리에서는 context를 만들 준비를 하고 실제 네이티브 함수를 구현합니다. 연결 SWC 는 context 를 만들고 context 와 플래시가 실행 할 수 있는 전역함수를 제공 합니다 그리고 마지막으로 extension.xml 은 AIR런타임이 연결 SWC 와 네이티브 라이브러리 사이의 연결을 정의 합니다.

다음 시간에는 지금까지 만든 파일들을 모두 build 폴더에 넣고 실제 ScreenWakeUp.ane 를 빌드 해 보도록 하겠습니다.

]]>
https://sewonist.com/%ec%97%b0%ea%b2%b0-swc-%eb%a7%8c%eb%93%a4%ea%b8%b0/feed/ 0
Android용 ANE 라이브러리 만들기 https://sewonist.com/android%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/ https://sewonist.com/android%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/#comments Wed, 15 Aug 2012 23:00:28 +0000 https://sewonist.com/?p=2958 Read More »Android용 ANE 라이브러리 만들기]]> 연재순서
  1. ANE 살펴보기
  2. iOS용 ANE 라이브러리 만들기
  3. Android용 ANE 라이브러리 만들기
  4. 연결 SWC 만들기
  5. ANE 빌드와 테스트 하기

작업환경

Android용 네이티브 라이브러리를 만들기 위해서는 ADT 즉 Android Development Toolkit이 필요합니다. 최신 이클립스를 설치하시고 플러그인으로 ADT를 설치하시면 됩니다. 자세한 설치방법은 다음의 링크를 참고하세요. ADT 설치하기, 안드로이드 SDK 설치하기, AVD 추가하기

  • Mac OS 10.7.4
  • Flex SDK 4.6.0 for AIR3.3
  • Eclipse 4.2.0
  • Android Development Toolkit 20.0.0

소스 다운로드

[button url=’https://github.com/sewonist/ScreenWakeUp’ target=’_blank’ size=’large’]Sources in GitHub[/button]

시작점 만들기

신규 안드로이드 프로젝트 생성

이클립스에 정상적으로 안드로이드 SDK 설치 되었다면 위의 이미지와 같이 신규 프로젝트에 Android 가 추가된 것을 확인 할 수 있습니다. Android Application Project를 선택합니다.

어플리케이션 이름 지정

어플리케이션 이름을 지정해 줍니다. Build SDK는 설치된 SDK 이고 Minimum Required SDK는 최소 필요 SDK입니다. 이 최소SDK 에 따라 사용 할 수 있는 기능에 차이가 있을 수 있습니다.

Activity 제거

Create Activity 는 일반 안드로이드앱을 만들 때를 위한 기본 템플릿 입니다. ANE를 위한 라이브러리에서는 필요 없는 기능이므로 체크를 해제 하고 프로젝트 생성을 완료 합니다.

FlashRuntimeExtensions.jar 복사

플래시와 네이티브 라이브러리를 연결하기 위해 사용 할 각종 함수와 정의가 있는 FlashRuntimeExtenshion.jar 파일을 복사합니다. 이 파일은 일반적으로 {Flash Builder 설치 경로}/sdks/{SDK 버전}/lib/android 폴더 안에 위치 합니다.

프로젝트 폴더로 복사

FlashRuntimeExtenshion.jar 을 좀전에 만든 프로젝트 폴더의 libs폴더에 복사 합니다. Android 의 경우에는 libs 폴더안의 jar 파일은 자동으로 참조하니 따로 프로젝트에 등록 할 필요는 없습니다.

코드작성

Android 용 네이티브 라이브러리는 작성은 iOS용과 약간의 차이가 있습니다. iOS용이 C 의 구조체를 이용한 방식이라면 Android는 Java의 클래스를 이용하고 있습니다. 이는 단순히 언어의 문법적 차이일뿐 실제 작동 방식은 거의 유사합니다.

ScreenWakeUpExtension 생성

[java]
package it.ane.screenwakeup;

import android.util.Log;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREExtension;

public class ScreenWakeUpExtension implements FREExtension {

@Override
public FREContext createContext(String arg0) {

Log.e("ScreenWakeUp", "call createContext");

return new ScreenWakeUpContext();
}

@Override
public void dispose() {
}

@Override
public void initialize() {
}

}
[/java]
ScreenWakeUpExtension 클래스는 FREExtension 인터페이스를 정의하고 있습니다. 저는 처음 Android용 ANE를 라이브러리를 만들 때 당연히 전부 클래스를 상속하려니 extends 를 했던 아픈 기억이 있습니다. 클래스 확장인 아닌 인터페이스 정의에 주의 하시기 바랍니다.

이 ScreenWakeUpExtension 은 extension.xml 에 정의 되어 있습니다. 그래서 AIR런타임 실행시 extension.xml을 참조하여 ScreenWakeUpExtension 의 createContext을 실행하여 context를 반환 받습니다. 인자 arg0은 ExtensionContext.createExtensionContext([extensionId], [contextTyoe]); 실행시 전달되는 contextType 입니다.

ScreenWakeUp 생성

[java]
package it.ane.screenwakeup;

import java.util.HashMap;
import java.util.Map;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;

public class ScreenWakeUpContext extends FREContext {

@Override
public void dispose() {
// TODO Auto-generated method stub

}

@Override
public Map<String, FREFunction> getFunctions() {
Map<String, FREFunction> map = new HashMap<String, FREFunction>();

map.put("isSupported", new IsSupportedFunction());
map.put("lock", new LockFunction());

return map;
}

}
[/java]
FREContext 를 확장하는 ScreenWakeUpContext 를 만듭니다. getFunctions() 함수를 통해 함수목록이 있는 map을 반환 합니다. map에 AIR에서 함수 호출시 사용할 이름과 함수의 인스턴스를 넣어 줍니다. C의 경우 함수에 대한 포인터 참조이나 Java의 경우 객체라는 점이 다릅니다. Java문법과 유사한 ActionScript에 익숙한 플래시 개발자들에게 좀더 익숙한 문법이 아닌 가 싶습니다.

LockFunction 생성

[java]
package it.ane.screenwakeup;

import android.app.Activity;
import android.content.Context;
import android.os.PowerManager;
import android.util.Log;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREInvalidObjectException;
import com.adobe.fre.FREObject;
import com.adobe.fre.FRETypeMismatchException;
import com.adobe.fre.FREWrongThreadException;

public class LockFunction implements FREFunction {

protected PowerManager.WakeLock mWakeLock;
private Boolean isLock;

@Override
public FREObject call(FREContext ctx, FREObject[] args) {

if(mWakeLock==null){
Activity activity = ctx.getActivity();
final PowerManager pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ScreenWakeUp");
isLock = false;
}

try {
Boolean flag = args[0].getAsBool();

if(flag==true && isLock==false){
this.mWakeLock.acquire();
} else if (flag==false && isLock == true) {
this.mWakeLock.release();
}

isLock = flag;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (FRETypeMismatchException e) {
e.printStackTrace();
} catch (FREInvalidObjectException e) {
e.printStackTrace();
} catch (FREWrongThreadException e) {
e.printStackTrace();
}

return null;
}

}
[/java]
실제 기능을 할 함수클래스를 작성합니다. LockFunction은 FREFunction 인터페이스를 정의하고 있는 것에 주의 하시기 바랍니다. 함수 인자를 살펴보면 ctx 는 context, args는 플래시에서 함수 호출신 전달되는 인자입니다. Android도 iOS와 마찬가지로 인자를 바로 사용하는 것이 아니라 getAsBool() 등의 함수를 통해 네이티브 변수로 변환 해야 합니다. 사용 할 수 있는 인자 타입은 아래와 같습니다.

  • getAsInt()
  • getAsDouble()
  • getAsBool()
  • getAsString()

위의 리스트는 FREObject의 경우이며 추가적으로 FREObject의 자식인 FREArray, FREBitmapData, FREByteArray 클래스도 사용할 수 있습니다.

[java]
Activity activity = ctx.getActivity();
final PowerManager pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ScreenWakeUp");

this.mWakeLock.acquire();

this.mWakeLock.release();
[/java]
실제로 화면잠금 구현부입니다. 여기서 재미난게 있습니다. PowerManager를 사용하기 위해서는 Activity 가 있어햐 하는데 우리는 이 Activity를 만든 적이 없습니다. 하지만 이미 AIR에 의해서 기본적으로 Activity가 만들어져 있기 때문에 ctx.getActivity(); 를 통해 바로 사용 할 수 있습니다.

참고로 Android 에서 이 기능을 사용하기 위해서는 아래의 퍼미션이 필요하므로 제작한 AIR앱의 -App.xml 에 아래의 퍼미션을 추가해야 합니다.
[xml]
<uses-permission android:name="android.permission.WAKE_LOCK" />
[/xml]

빌드

Export

Package Explorer 에서 프로젝트의 src 폴더를 우클릭해서 Export 합니다. 물론 다른 방법으로도 Export 할 수 있지만 이렇게 하는게 가장 깔끔하게 Export 됩니다.

JAR file

Export 는 Java 의 JAR file 을 선택 합니다.

완료

Export generated class files and resources 가 체크 활성화 되어 있는지 확인합니다. JAR 파일이 저장될 곳을 선택하고 완료합니다.

정리

Android 용 네이티브 라이브러리 만드는 법을 살펴 보았습니다. iOS와는 문법적으로 조금 다르나 기본적으로 context를 생성하고 함수 목록을 반환하야 사용하는 구조는 유사하다는 걸 알 수 있었습니다. 즉, extension.xml 에 의해 ScreenWakeUpExtension 이 실행되고 이어 각 기능 함수가 포함되어 있는 ScreenWakeUpContext가 반환되는 것 입니다. 함수들은 FREFunction 인터페이스만 정의 하고 있으면 내부적으로는 어떻게 작성되어도 무방합니다. 또한 예제에서는 편의를 위해 모든 파일을 따로 만들었지만 한파일에 모두 정의 되어 작성되어도 잘 작동하니 참고 하시기 바랍니다.

이제 다음 시간에는 앞서 만든 각 네이티브 라이브러리를 실제 플래시와 연결해 줄 연결 SWC 를 만들어 보도록 하겠습니다.

]]>
https://sewonist.com/android%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/feed/ 2
iOS용 ANE 라이브러리 만들기 https://sewonist.com/ios%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/ https://sewonist.com/ios%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/#respond Sun, 12 Aug 2012 10:29:41 +0000 https://sewonist.com/?p=2891 Read More »iOS용 ANE 라이브러리 만들기]]> 연재순서
  1. ANE 살펴보기
  2. iOS용 ANE 라이브러리 만들기
  3. Android용 ANE 라이브러리 만들기
  4. 연결 SWC 만들기
  5. ANE 빌드와 테스트 하기

작업환경

자 이제 본격적으로 ScreenWakeUp ANE 용 iOS 네이티브 라이브러리를 만들어 보도록 하겠습니다. 제 작업 환경은 아래와 같습니다.

  • Mac OS 10.7.4
  • Flex SDK 4.6.0 for AIR3.3
  • Xcode 4.3.3

저는 주로 모바일용을 만들고 있기 때문에 위와 같은 환경입니다. 사용자 마다 환경은 조금씩 다를 수 있는데 AIR3.3 이상의 Flex SDK만 있다면 ANE 를 만드는데 크게 상관은 없습니다. 일단 제가 가지고 있는 시스템이 맥이다 보니 맥을 기준으로 글을 작성 할 예정입니다.

소스 다운로드

[button url=’https://github.com/sewonist/ScreenWakeUp’ target=’_blank’ size=’large’]Sources in GitHub[/button]

시작점 만들기

개발 폴더 구조

위의 개발 폴더 구조는 제가 다른 여러 ANE 제작자들의 폴더구조를 보고 만든 방법입니다. Android 와 Xcode 는 각 네이티브 라이브러리를 만들 프로젝트 폴더이고 SWC는 연결 SWC, Flash 폴더는 테스트 플래시 프로젝트 폴더입니다 마지막으로 build는 각 네이티브 라이브러리, SWC 그리고 extension.xml 을 넣어서 빌드를 하는 폴더 입니다. 위의 구조는 임의 이므로 편하신대로 다시 세팅하여도 무방합니다.

그럼 Xcode 프로젝트를 생성해 보도록 하겠습니다.

Cocoa Touch Static Library 프로젝트 생성

File -> New -> Project… 메뉴를 통해서 Cocoa Touch Static Library 프로젝트를 생성합니다.

프로젝트 이름 입력

프로젝트 이름을 입력하고 프로젝트 생성을 완료 합니다.

FlashRuntimeExtenshion.h 복사

플래시와 네이티브 라이브러리를 연결하기 위해 사용 할 각종 함수와 정의가 있는 FlashRuntimeExtenshion 헤더 파일을 복사합니다. 이 파일은 보통 {Flash Builder 설치 경로}/sdks/{SDK 버전}/include 폴더 안에 위치 합니다.

프로젝트 폴더로 복사

FlashRuntimeExtenshion.h 파일을 좀전에 만든 프로젝트 하위 폴더에 복사 합니다.

프로젝트에 헤더파일 추가

헤더파일 선택

Xcode 프로젝트는 폴더에 파일을 복사해도 프로젝트에서 자동으로 인식 하지 않으므로 위와 같은 방법을 프로젝트에 복사한 FlashRuntimeExtenshion.h 을 등록합니다.

코드작성

이제 iOS용 ANE 라이브러리를 만들 준비가 전부 되었으므로 실제 코드를 살펴 보도록 하겠습니다. 지난 시간에 광고한대로 이번 시간부터는 ScreenWakeUp 이라는 ANE를 직접 만들고 소스를 분석해 보도록 하겠습니다. ScreenWakeUp 은 스마트폰의 화면자동 잠금 기능을 무효화 하고 화면이 계속 켜져 있도록 해주는 ANE 입니다.

[c]
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FlashRuntimeExtensions.h"

@interface ScreenWakeUp : NSObject

@end
[/c]

Xcode 프로젝트를 생성하고 나면 자동으로 생성되는 ScreenWakeUp.h 파일에 FlashRuntimeExtensions.h 파일을 임포트 합니다. 이제 앞으로 ScreenWakeUp.h 를 임포트하는 ScreenWakeUp.m 파일에서 FlashRuntimeExtensions.h 에 정의된 모든 기능을 사용 할 수 있습니다.

그럼 바로 ScreenWakeUp.m 전체소스를 보고 부분씩 살펴 보겠습니다.

[c]
#import "ScreenWakeUp.h"

@implementation ScreenWakeUp

@end

FREObject isSupported(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ){
FREObject retVal;
if(FRENewObjectFromBool(YES, &retVal) == FRE_OK){
return retVal;
}else{
return nil;
}
}

FREObject lock(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ){
//Temporary values to hold our actionscript code.
uint32_t boolean;

//Turn our actionscrpt code into native code.
FREGetObjectAsBool(argv[0], &boolean);

if(boolean){
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
} else {
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
return nil;
}

void ContextInitializer(void* extData, const uint8_t * ctxType, FREContext ctx,
uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet)
{
int count=2;

*numFunctionsToTest = count;
FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * count);

func[0].name = (const uint8_t *) "isSupported";
func[0].functionData = NULL;
func[0].function = &isSupported;

func[1].name = (const uint8_t *) "lock";
func[1].functionData = NULL;
func[1].function = &lock;

*functionsToSet = func;
}

void ContextFinalizer(FREContext ctx) {
return;
}

void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet,
FREContextFinalizer* ctxFinalizerToSet) {
*extDataToSet = NULL;
*ctxInitializerToSet = &ContextInitializer;
*ctxFinalizerToSet = &ContextFinalizer;
}

void ExtFinalizer(void* extData) {
return;
}
[/c]

처음 보면 다소 복잡해 보이는 코드이지만 하나하나 나눠서 보면 그리 어렵지 않습니다. 먼저 확인해햐 하는 함수는 ExtInitializer 입니다.

[c]
void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet,
FREContextFinalizer* ctxFinalizerToSet) {
*extDataToSet = NULL;
*ctxInitializerToSet = &ContextInitializer;
*ctxFinalizerToSet = &ContextFinalizer;
}
[/c]
이는 extension.xml 에 명시되어진 함수로 처음 context 가 만들어지면서 호출 되는 함수 입니다. 인자로 extDataToSet, ctxInitializerToSet, ctxFinalizerToSet 의 포인터를 받습니다. 시작하자마자 멘붕이 오기 시작합니다. * 은 뭐고 & 는 뭐고 심지어 ** 은 뭔가요? *을 저리 많이 쓴걸 보니 뭔가 중요한건가 봅니다. ㅎㅎㅎ 이걸 제대로 이해하기 위해서는 직업을 c 개발자로 전향 해야 될지도 모르니 의미 만 간단히 살펴보면 걍 ContextInitializer 와 ContextFinalizer 를 참조하겠다 입니다. 그리고 당연하게 필요한 시기에 호출해서 사용하겠지요. 그 시기란 AIR런타임이 context 를 만드는 시점 일 겁니다. 여튼 이 함수를 통해서 AIR와 네이티브간의 첫 접선이 이루어졌고 우리는 자연스럽게 ContextInitializer 함수가 실행 될 것이라는 걸 추측 할 수 있습니다.

[c]
void ContextInitializer(void* extData, const uint8_t * ctxType, FREContext ctx,
uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet)
{
int count=2;

*numFunctionsToTest = count;
FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * count);

func[0].name = (const uint8_t *) "isSupported";
func[0].functionData = NULL;
func[0].function = &isSupported;

func[1].name = (const uint8_t *) "lock";
func[1].functionData = NULL;
func[1].function = &lock;

*functionsToSet = func;
}
[/c]
ContextInitializer 함수의 주기능은 실제로 사용하게 될 함수를 등록하는 일입니다. 이 시점에 우리는 네이티브 코드를 위해 context 를 변수에 저장 해 둘 수 도 있습니다.

위의 코드에서 주의깊게 봐야 할 부분은 먼저 int count=2 입니다. 소스를 잘 보시면 count는 numFunctionsToTest 와 functionsToSet 을 위한 func 생성시 메모리 크기 또한 지정해 주고 있습니다. 메모리 관리에 대한 개념이 별로 없는 플래시 개발자들이 C언어에서 가장 많이 힘들어 하는 부분입니다. count를 2로 생성했으면 이후에 오는 배열크기도 이와 반드시 동일 해야 합니다. 즉 func[3] 와 같이는 사용 할 수 없습니다.

func 구조체의 name 인자는 플래시에서 ExtensionContext call() 호출시 사용 하는 이름 입니다. functionData 는 function 실행시 전달되는 데이터 입니다. 그닥 사용 할 일은 많지 않을 것 같습니다. function은 실제로 호출될 함수에 대한 참조 입니다.

그리고 추가적으로 함수인자로 넘어오는 ctxType 은 연결 연결 SWC 에서 context를 생성하는 함수인 ExtensionContext.createExtensionContext([extensionId], [contextTyoe]); 실행시 contextType 에 들어가는 인자로 하나의 ANE 에서 다른 종류의 기능인 있는 context 를 만들 수 있게 해줍니다.

[c]
FREObject lock(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ){
//Temporary values to hold our actionscript code.
uint32_t boolean;

//Turn our actionscrpt code into native code.
FREGetObjectAsBool(argv[0], &boolean);

if(boolean){
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
} else {
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
return nil;
}
[/c]
실제로 우리가 원하는 기능을 구현할 함수부 입니다. 먼저 전달 인자 부터 보겠습니다. ctx는 계속 나오고 있는 context 입니다. funcData는 좀전에 ContextInitializer 에서 func 생성시 지정한 funcData 입니다. argc는 플래시로부터 넘어오는 인자 argv 배열의 갯수 입니다. argv는 플래시에서 실제로 넘어노는 인자값 배열 입니다.

[c]
//Temporary values to hold our actionscript code.
uint32_t boolean;

//Turn our actionscrpt code into native code.
FREGetObjectAsBool(argv[0], &boolean);
[/c]
플래시에서 넘어온 인자를 네이티브에서 사용하기 위해서는 위의 코드와 같이 지정된 함수를 통해서 네이티브용 값으로 변환해 주어야 합니다. 현재 가져올 수 있는 데이터 타입은 아래의 표와 같습니다.

  • FREAcquireBitmapData()
  • FREAcquireBitmapData2()
  • FREAcquireByteArray()
  • FREGetArrayElementAt()
  • FREGetArrayLength()
  • FREGetObjectAsBool()
  • FREGetObjectAsDouble()
  • FREGetObjectAsInt32()
  • FREGetObjectAsUint32()
  • FREGetObjectAsUTF8()

타입에 따라 사용법은 조금씩 상이 합니다. 그리고 함수에서 결과 값을 반환 받는 방식이 아닌 인자로 들어간 포인터에 값이 저장 되는 형식이 특이해 보입니다. 여담으로 dieBuster 를 방문해 보시면 함수와 인자에 대한 좋을 글을 보실 수 있습니다.

[c]
if(boolean){
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
} else {
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
[/c]
드디어 정말 우리가 필요로 하는 코드가 나왔습니다. 뭔가 거창하게 시작했는데 너무 싱겁나요? ㅎㅎㅎ iOS에서는 기본적으로 위와 같은 메소드를 제공 하고 있으므로 setIdleTimerDisabled 을 호출 하는 것 많으로 아주 간단하게 우리가 원하는 화면잠금 기능을 구현 할 수 있습니다. 다음 연제에 나올 Android 버전은 조금 더 복잡하니 너무 실망하지 마세요~^^

참고로 제가 테스트 해본결과 ANE 용 라이브러리를 만들때 C, C++ 그리고 Object-C가 위의 코드 처럼 섞여 있어도 문제없이 잘 작동하였습니다.

빌드

빌드경로 수정

간혹 빌드를 한 파일이 안보이는 경우가 있는데 제 경우에는 빌드 설정에서 빌드 패스를 위의 이미지 처럼 상대경로로 설정해 줍니다. 그럼 아래의 이미지 처럼 프로젝트 폴더의 한단계 상위에서 최종적으로 빌드된 파일을 확인 할 수 있습니다.

최종 결과물

정리

지금까지 iOS 용 ANE 네이티브 라이브러리를 만드는 과정에 대해서 알아보았습니다. 간단히 순서를 요약하면 Xcode 에서 Cocoa Touch Static Library 프로젝트를 만든다. FlashRuntimeExtenshion.h 를 프로젝트에 추가한다. ExtInitializer -> ContextInitializer -> 함수 순으로 등록하여 사용한다. 정도로 정리 할 수 있을 겁니다.

이제 ANE를 만들기 위한 첫발을 내딛었습니다. 다음 시간에는 iOS용과는 또다른 구조로 되어있는 Android 용 라이브러리를 만들어 보도록 하겠습니다.

– 참고 –
http://help.adobe.com/en_US/air/extensions/WSb464b1207c184b14-62b8e11f12937b86be4-8000.html

p.s. 우야꼬님도 ANE에 대한 연재를 시작하셨네요. 같이 보시면 더욱 좋을 것 같습니다. Native Extension for iOS 만들기 Part.1 – iOS 개발

]]>
https://sewonist.com/ios%ec%9a%a9-ane-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0/feed/ 0
ANE 살펴보기 https://sewonist.com/ane-%ec%82%b4%ed%8e%b4%eb%b3%b4%ea%b8%b0/ https://sewonist.com/ane-%ec%82%b4%ed%8e%b4%eb%b3%b4%ea%b8%b0/#comments Sun, 05 Aug 2012 23:29:03 +0000 https://sewonist.com/?p=2855 Read More »ANE 살펴보기]]> 연재순서
  1. ANE 살펴보기
  2. iOS용 ANE 라이브러리 만들기
  3. Android용 ANE 라이브러리 만들기
  4. 연결 SWC 만들기
  5. ANE 빌드와 테스트 하기

ANE 란 AIR Native Extensions 의 약자로 이름 그대로 AIR 에서 네이티브 코드를 사용 할 수 있게 해주는 AIR 확장 툴입니다. 저는 앞으로 5회에 걸쳐 ANE 에 대해서 알아보고 어떻게 만들고 사용 할 수 있는지 알아 보려고 합니다. 오늘은 그 첫시간으로 ANE 에 대해서 간략 하게 알아 보도록 하겠습니다.

ANE 란?

ANE는 Adobe AIR 와 운영체제의 네이티브 라이브러리를 서로 연결 해 주는 연결점(context) 라고 생각하시면 이해하기 편합니다.주로 AIR가 네이티브 라이브러리의 함수를 호출하고 데이터를 주고 받는 형태로 이루어져 있습니다. 흔히들 AIR3.0 에서 모바일을 지원하며 대대적으로 알려졌지만 실제로는 AIR2.5 for TV에서 처음 등장하였습니다.

ANE는 다음의 두 가지 방법 중 하나로 작동 할 수 있습니다.
애플리케이션 번들링 애플리케이션 번들링이 앞으로 저희가 주로 알아볼 방식으로 제작된 AIR 애플리케이션에 네이티브코드가 포함되어 실행되는 방식을 말합니다. ANE에 따라서 멀티플렛폼을 지원하도록 만들 수도 있고 경우에 따라서는 네이티브코드를 지원하지 않는 경우를 위해 액션스크립트만 포함 할 수도 있습니다.

디바이스 번들링 디바이스 번들링은 네이티브 코드가 디바이스에 포함되는 경우로 AIR2.5 for TV 의 ANE가 대표적입니다. 주로 네이티브코드를 TV제작업체에서 제공합니다.

아래의 표는 애플리케이션 번들링과 디바이스 번들링이 지원하는 디바이스를 보여 줍니다.

ANE 로 할 수 있는 것들

특화된 기능

ANE 는 시스템에 특화된 기능들을 사용 할 수 있게 해줍니다. 예를 들어 핸드폰에 있는 진동이라던가 안드로이드의 알람과 같이 기본 AIR API에 없는 기능을 사용 할 수 있습니다. 이러한 시스템 특화된 기능을 Adobe 에서 지원해 주기를 기대하는 것은 어렵습니다. Adobe는 당연하겠지만 범용으로 사용 할 수 있는 API  업데이트에 중점을 두고 있으니까요. 그래서 ANE라는 중간역활을 두어 개발자들에게 필요한 것들을 개발 할 수 있는 문을 열어 주었습니다. 어떻게 보면 인터넷 생태계가 급속도록 모바일로 이동하면서 Adobe가 내놓은 궁여지책 일 수도 있습니다. 하지만 실제로 ANE가 AIR2.5 for TV  부터 지원했다는 사실을 보면 내부적으로 이러한 상황을 염두하고 있었던 것 같습니다.

좀더 현실적으로 보면 이로서 시스템의 자원을 AIR에서 바로 사용할 수 있게 된것입니다. 예를 들어 기존에는 특정 드라이버를 이용해야 하는 경우 AIR에서 직접 접근 할 방법이 없으므로 중간에 프록시서버등을 통해서 소켓으로 통신하곤 하였습니다. 하지만 이제 더 이상 그럴 필요 없이 ANE 를 통해 바로 연결 할 수 있습니다.

키넥트에 연결하기 위해 더 이상 소켓서버가 필요없다.

훌륭한 코드들

전통적인 C, C++ 그리고 Java와 같은 언어를 사용 할 수 있게 됨으로서 기존의 검증된 훌륭한 코드들을 빠르고 쉽게 사용 할 수 있습니다. ANE를 통해 이러한 코드를 랩핑하여 앞으로 ActionScript 통해 만들 어플리케이션에서도 이러한 코드를 사용 할 수 있게 되었습니다.

성능

ANE 는 가장 높은 수준의 최적화를 구현 할 수 있습니다. ANE를 사용함으로서 기대 할 수 있는 성능 향상은 첫째 컴파일된 C 코드를 통한 최고의 퍼포먼스, 두번째로 병렬 알고리즘으로 큰 효과를 볼 수 있는 멀티코어의 사용, 마지막으로 GPU 가속을 통한 성능 향상을 기대 할 수 있습니다. 제가 만든 앱을 통해서 테스트 해 본 결과 암호화와 같은 특정상황에서는 엄청난 성능의 차이를 체감 할 수 있었습니다.

ANE 단점

시스템 종속성

ANE의 시스템에 특화된 기능을 사용 할 수 있는 특징은 결국 시스템에 종속적으로 만들어 버립니다. ANE를 도입하는 순간 플래시의 큰장점인 원소스 멀티플렛폼을 포기해야 하는 상황이 발생합니다. 물론 ANE를 도입해야 하는 시점에서 이미 어느정도 멀티플랫폼을 포기해야 할 컨테츠라는 점이 조금은 다행이긴 합니다만 예를 들어 무료컨텐츠에 광고 솔루션을 붙힌 어플리케이션의 경우 보통 ANE로 작성된 광고 솔루션을 사용하게 되는데 AdMob을 붙힌 어플리케이션은  iOS에 사용 할 수 없게되는 상황이 발생 하게 된다는 점입니다. 심지어 iOS용으로 만든 라이브러리의 경우 ARM용으로 빌드한 것은 x86으로 돌아가는 아이폰 시뮬레이션에서는 작동 하지 않습니다.

불편한 디버그

뒤에 좀 더 자세히 알아보겠지만 ANE 가 최종적으로 실행 되는 모습을 보기 위해서는 다음의 세 레이어층이 필요합니다. 1.네이티브 코드 2.연결 SWC 3.어플리케이션 입니다. 실제로 우리가 ANE 라고 부르는 영역은 1번과 2번 까지 입니다. 하지만 실제로 ANE 를 만들고 테스트 하기 위해서는 디바이스에서 돌아가는 3번 어플리케이션 까지 작성해야 합니다. 그리고 ANE와 어플리케이션이 전혀 다른 루트로 디버그툴을 제공하므로 디버그가 상당히 불편한 편입니다. 가장 좋은 솔루션은 네이티브코드를 작성할때 테스트 케이스를 만들어 네이티브코드에 대한 무결성을 보장하는 겁니다.

ANE 구조

이제 ANE 파일의 실제구조를 알아보겠습니다. ANE는 단순히 네이티브코드와 연결SWC의 libaray.swf 그리고 이들의 관계를 정의한 extension.xml 의 압축파일입니다. 파일트리는 다음 과 같습니다.

[xml]
mimetype
META-INF/ANE/extension.xml
catalog.xml
library.swf
META-INF/ANE/Android-ARM/library.swf
META-INF/ANE/Android-ARM/ScreenWakeUp.jar
META-INF/ANE/iPhone-ARM/library.swf
META-INF/ANE/iPhone-ARM/libScreenWakeUp.a
[/xml]

앞으로 연제를 하며 만들어 볼 ScreenWakeUp의 ANE 트리구조 입니다. AIR는 시스템을 확인 후 extension.xml을 토대로 context를 생성 하게 됩니다. extension.xml을 한번 보겠습니다.

[xml]
<extension xmlns="http://ns.adobe.com/air/extension/3.1">
<id>it.ane.ScreenWakeUp</id>
<versionNumber>1.1</versionNumber>
<platforms>
<platform name="iPhone-ARM">
<applicationDeployment>
<nativeLibrary>libScreenWakeUp.a</nativeLibrary>
<initializer>ExtInitializer</initializer>
<finalizer>ExtFinalizer</finalizer>
</applicationDeployment>
</platform>

</platforms>
</extension>
[/xml]

여기서 주의깊게 봐야 할 부분은 <id> 와 <initializer> 입니다. 다음 ANE만들기에서 다시 자세히 살펴보겠지만 간단히 살펴보면 <id>는 연결SWC 에서 다음의 코드로 context를 만들때 사용하는 아이디 입니다.

[as3]
private static const EXTENSION_ID:String = "it.ane.ScreenWakeUp";
ExtensionContext.createExtensionContext(EXTENSION_ID, null);
[/as3]

그리고 <initializer> 의 값은 네이티브코드에 정의된 함수로 FlashRuntimeExtensions.h 에 의해 전달된 context에 함수를 등록하는 함수입니다. 이렇게 함으로서 연결SWC 와 네이티브코드가 context를 통해 연결되게 됩니다.

정리

Adobe가 ANE를 처음(?)소개 했을 때 많은 플래시 개발자들이 열광했습니다. 저도 그들 중 한명이었구요. 모바일시대에 들어서면 플래시의 입지가 줄어들대로 줄어든 상황에서 ANE는 마치 한줄기 구원의 빛과 같았습니다. 하지만 ANE는 장점만큼이나 신경써야할게 많은 기술입니다. 특히 ANE의 핵심인 네이티브코드 부분은 일반 플래시개발자에게는 너무나 생소한 영역입니다. 그러다 보니 많은 분들이 ANE 에 관심은 있지만 실제로 쉽게 접근하기 힘든게 사실입니다. 하지만 차근차근 살펴보면 생각보다 어렵지 않습니다. 가능한 쉽게 설명하려 했으나 조금 뜬구름 잡는 느낌이 있는데 이후 연제에서 실제로 샘플을 만들어 보면 더 쉽게 이해 할 수 있으리라 생각 됩니다.

다음 시간 부터는 ScreenWakeUp 이라는 이름의 ANE를 실제로 만들어 보도록 하겠습니다. 이 ANE는 스마트폰의 화면을 켬 상태로 잠궈주는 기능을 합니다. 만약 AIR를 이용해 비디오 플레이어 같은 어플을 만들경우 유용하게 사용 할 수 있을 겁니다.

– 참고 –
http://www.adobe.com/devnet/air/articles/extending-air.html
http://help.adobe.com/en_US/air/extensions/air_extensions.pdf

]]>
https://sewonist.com/ane-%ec%82%b4%ed%8e%b4%eb%b3%b4%ea%b8%b0/feed/ 5
Future of Flash https://sewonist.com/future-of-flash/ https://sewonist.com/future-of-flash/#comments Thu, 07 Jun 2012 16:53:49 +0000 https://sewonist.com/?p=2809 Read More »Future of Flash]]>

먼저 상당히 어그로를 끌 수 있는 제목을 선택 한 점 사과드립니다. 이번 포스팅은 플래시의 미래와는 그닥 관련이 없습니다. 오랜만에 글 올려서 인기 좀 끌어 보려는 수작입니다. ^_^

몇일 전 우연히 앞으로 플래시 개발 로드맵 문서를 보았습니다. 이미 보신 분들도 있으시겠지만 안 보신분들을 위해서 한줄요약 해드리면 “앞으로 플래시는 게임과 비디오를 위해서 발전할거야!!!” 정도로 압축 할 수 있을 것 같습니다. 그런데 여기서 얼마전 게임 개발 할때 성능을 올리고 싶으면 라이센스를 사야한다는 부분이 이슈가 되었던 적도 있습니다. 이미 어도비가 당연히 올려야 했을 성능을 위해 왜 개발자에게 그 비용을 물게 하느냐는게 내용이였는데 저도 정확하게 어떻게 돌아가는 내용인지는 몰라 그냥 그런 일이 있구나 정도로만 알고 있습니다.

여튼 저는 어도비가 그러든 말든 열심히 잉여잉여 하고 있습니다;;; 그러면서 만든게 아래의 뮤직비디오 입니다. 플래시 플레이어 11 이상이 필요하고 파일 사이즈가 6메가라 다운로드에 조금 시간이 걸립니다.

저는 최근 계속해서 플래시를 통한 3D 컨텐츠 제작에 관심을 갖고 있습니다. 제 블로그에서 DAE 로 검색하시면 Away3D 와 DAE 에니메이션 관련 자료를 몇 보실 수 있습니다. 요 몇년사이에 기술이 정말 빠르게 발전해서 위와 같은 영상도 아주 쉽게 만들 수 있는 세상이 되었습니다. MMD -> Cinema4D -> Unity3D -> Flash 라는 과정을 거치기는 했지만 뭐 여튼 그렇게 어렵지는 않습니다.^^;;

위의 영상은 위의 과정을 통해 다음과 같은 것들이 가능한지 테스트 해보았습니다.

성공

  1. 하이폴리곤 모델링 데이터 가져오기
  2. 본 베이스 에니메이션 가져오기
  3. 라이트
  4. 3D 사운드
  5. 파티클

실패

  1. Cloth 시뮬레이션
  2. Physics
  3. 폴리곤 몰핑 애니메이션

사실 제가 하고 싶은 궁국의 목표는 위에 열거한 사항을 Unity3D 의 도움없이 Flash 로 바로 만드는 것 입니다. 그래야 양질의 3D 에니메이션을 제가 넣고 싶은곳에 맘대로 넣을 수 있는데 아직까지는 여러가지 제약이 있어 힘드네요. 혹시 좋은 아이디어나 의견 있으신 분은 언제든지 연락주세요. 여튼 저는 이리 삽질을 하고 있는 동안 아래와 같이 멋진 기술들이 나와 눈을 즐겁게 하네요.

Unity3D 를 쓰면서 참 아쉬운 부분이 때깔인데 언리얼은 그나마 때깔이 이쁘네요. http://www.unrealengine.com/flash/ 에서 실시간으로 구경 할 수 있습니다. 사실 이 글을 맨 아래 Agni’s Philosophy 를 보고 띵 받아 작성 했습니다.

플래시도 할 수 있다는 걸 보여주려 했지만 결과는 … OTL

Unreal Engine 3 support Adobe Flash Player

Unreal Engine 3 Samaritan Demo con DirectX 11

Agni’s Philosophy — FINAL FANTASY REALTIME TECH DEMO

참고로 위의 영상 3개는 모두 실시간 플레이 화면~!!!

]]>
https://sewonist.com/future-of-flash/feed/ 5
how to flash develop on terminal https://sewonist.com/how-to-flash-develop-on-terminal/ https://sewonist.com/how-to-flash-develop-on-terminal/#respond Thu, 12 Jan 2012 02:44:13 +0000 https://sewonist.com/?p=2701 Read More »how to flash develop on terminal]]> 여러분은 어떤 툴로 플래시를 개발 하시나요? 플래시를 개발 할 수 있는 툴은 참 다양하게 있습니다. SWF 포멧 자체가 공개 되어 있기 때문에 심지어 바이너리를 수정 해서도 만들 수 있습니다. 일반적인 경우 Flash IDE 나 Flash Builder 를 많이 이용 하지요. 저 같은 경우 재작년 까지는 Flash Develop 이 가벼워서 애용하다가 최근에는 Flash Builder 에서 주로 작업을 하고 있습니다. 모두 좋은 툴이므로 본인의 상황에 맞게 이용하면 되겠지요.

그런데 근래에 들어 사용횟수가 부쩍 늘어난게 있는데 바로 Vim 입니다. 정확하게는 터미널에서 작업을 한다고 해야 되겠네요. 터미널에서 작업을 하면 가장 좋은게 더 이상 마우스 질을 하기 위해서 손을 움직이지도 않아도 된다는 겁니다. 디자이너 출신인 제가 마우스 질 하기가 귀잖다는게 참 아이러니 하네요. ㅎㅎㅎ 여튼 그래서 터미널에서 플래시를 개발하는 방법과 유용한 Vim 플러그인을 소개 해 보겠습니다. 참고로 테스트 환경은 MaxOS X 10.7.2, Vim 7.3 입니다.

1. Download lastest Flex SDK or Flash Builder

2. Setting PATH & alias
[bash]
export PATH=/usr/local/git/bin:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin: /usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/opt/local/bin:/usr/local/git/bin:/Applications/Adobe Flash Builder 4.5/sdks/4.5.1_AIR3/bin

alias flash=’/Applications/Adobe Flash Builder 4.5/player/mac/11.1/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger’
[/bash]
빌드를 편하게 하기 위해서 PATH 와 단축키를 설정 합니다. PATH 에는 빌더의 bin 폴더를 alias 에는 사용할 플레이어 실행 파일을 설정합니다. 플레이어의 경우 절대경로 상에서 실행하지 않으면 안되므로 alias 로 만들어 줘야 합니다. 이렇게 하면 간단하게 mxmlc 로 컴파일 하고 flash 로 실행 할 수 있게 됩니다.

3. Download Vundle
Vim 플러그인 관리툴 입니다. 한번에 간단하게 플러그인 들을 설치/관리 할 수 있습니다. 파일트리를 볼 수 있는 NERD Tree 와 actionscript syntax 를 해주는 vim-actionscript 등을 유용한 플러그인을 설치 할 수 있습니다.

4. Download AutoComplPop
Vim 같은 터미널 에디터를 쓸 때 참 아쉬운게 자동완성 기능인데 IDE 처럼 완벽하지는 않지만 나름 코딩시간을 많이 줄여 줍니다.

5. Setting .vimrc
[bash]
" my setting
set nu
set autoindent
set smartindent
syntax enable

set nocompatible " be iMproved
filetype off " required!

set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

" let Vundle manage Vundle
" required!
Bundle ‘gmarik/vundle’

" My Bundles here:
"
" original repos on github
Bundle ‘tpope/vim-fugitive’
Bundle ‘Lokaltog/vim-easymotion’
Bundle ‘rstacruz/sparkup’, {‘rtp’: ‘vim/’}
Bundle ‘tpope/vim-rails.git’
Bundle ‘jeroenbourgois/vim-actionscript’
Bundle ‘scrooloose/nerdtree’
" vim-scripts repos
Bundle ‘L9’
Bundle ‘FuzzyFinder’
" non github repos
Bundle ‘git://git.wincent.com/command-t.git’
" …

filetype plugin indent on " required!
"
" Brief help
" :BundleList – list configured bundles
" :BundleInstall(!) – install(update) bundles
" :BundleSearch(!) foo – search(or refresh cache first) for foo
" :BundleClean(!) – confirm(or auto-approve) removal of unused bundles
"
[/bash]
Vundle 설치를 위한 설정과 자동들여쓰기 옵션 등을 본인의 기호에 맞게 설정합니다. 대충의 설정이 끝났습니다. 이제 열심히 코딩 합시다. ^^

영상은 어웨이에 구를 넣어 swf 를 만들기 까지 vim 과 builder 코딩시간비교 입니다. 원래 목표는 “vim 이 훨씬 빨라요.” 뭐 이런 결과를 보여드리고 싶었는데 별반 차이가 없네요. ㅎㅎㅎ

]]>
https://sewonist.com/how-to-flash-develop-on-terminal/feed/ 0
Today Site 2011.06.08 https://sewonist.com/today-site-2011-06-08/ https://sewonist.com/today-site-2011-06-08/#respond Wed, 08 Jun 2011 12:35:28 +0000 https://sewonist.com/?p=2380 Read More »Today Site 2011.06.08]]>

정확하게 어느나라인지는 모르겠지만 (아마 프랑스 인듯..) 좀비 드라마 사이트 입니다. 그 중에서도 게임부분 입니다. 영화와 같은 컨셉으로 플래시 게임을 만들어 흥미를 유발하고 있습니다. 특히 게임은 풀 3D로 만들어져 있습니다.

제가 이 사이트를 소개하고 제가 관심을 가지는 이유는 바로 게임데이터를 Cinema4D 에서 작업했기 때문입니다.

사실 플래시에서 3D 작업을 할 때는 맥스가 편리한게 사실입니다. 특히 Collada 파일 추출과 연동시는 더욱 그렇습니다. 캐릭터모델링과 애니메이션을 가져오려면 아직까지는 Collada 파일 포멧만 한게 없습니다. 그런데 이 포멧이 어차피 XML 이라 exporter 마다 조금씩 다른 모습입니다. 그래서 맥스 이외의 exporter 에서 추축한 데이터는 Away3D 같은 3D 라이브러리에서 인식을 못하는 경우가 많았습니다. 그럼에도 불구하고 Cinema4D를 이용해서 이 정도 퀄리티의 게임을 만들었다는 건 분명 좋은 솔루션이 이미 개발 되었음을 의미합니다.

그리고 게임자체의 완성도도 상당히 높은데 정말 모힐이 나와 그래픽만 조금더 좋아지면 왠만한 콘솔게임 안 부러울 것 같습니다.(사실 모힐의 좋은 점은 그래픽이 좋아지는 것도 있지만 CPU 점유율이 낮아지는 것도 상당합니다.)

이 게임을 리버스엔지니어링 해서 자세히 연구해 봐야겠습니다. 그나저나 급 리깅 공부하고 싶어지넹~~~ㅎㅎㅎ

http://demos.hellohikimori.com/walking-dead/jeu/

]]>
https://sewonist.com/today-site-2011-06-08/feed/ 0