Home > Progression
Progression Archive
extends Progression 拡張機能コンテストで Progression 開発者賞受賞
- 2009-06-15 (月)
- ActionScript | Flash | Progression
半年ほどブログ放置してすいません・・・
extends Progression 拡張機能コンテスト
http://extends.progression.jp/
Progression 開発者賞というものをいただいてしまいました!
感謝感激です。
しかも、予定にはなかった Progression 開発者賞という賞を新設していただくという暖かい配慮に心より感謝感謝です。
extends Progression 拡張機能コンテスト関係者の皆様本当にありがとうございました!
今回応募したものは LiquidLayout というライブラリです。
フルフラッシュサイトを作るときに、AS3になってからもっとやっかいになってしまった表示オブジェクト等の配置をカンタンにしちゃえというライブラリです。
ExDocument をルートシーンに使用していれば、LiquidLayout も利用可能という代物になっており、Progression に限らず利用できてしまうので、このあたりが Progression 開発者賞を新設していただけるという関係者の皆様を困惑させてしまう結果になってしまったようです。taka:niumさんすいません!
提出したプレゼン資料
(Slideライブラリ使用。左右キーで移動します)
サンプルデモ
(設定を変えたり、画面をぐりぐりリサイズしてご確認ください)
ソース一式
(サンプルデモで使用したクラスファイルも同梱しています)
Tweener を同じような構造をとっており、addLayout メソッドでオブジェクトとパラメータを追加して使用します。
数値で指定した画面位置からの距離、数値を文字列で渡すことによりパーセンテージでの指定が可能です。
Tweener ライブラリと大きく異なる部分は、Tweener は静的メソッドでアクセスするのに対し、LiquidLayout はインスタンスを生成して使用します。
var lauout:LiquidLayout = new LiquidLayout( document ); layout.addLayout( mc, { center: 0, middle: 0 } );
この部分は最後まで悩んだというか今現在でも悩んでいるのですが、オブジェクトの最大幅・最小幅・最大高さ・最小高さなどを、インスタンス本体が持っていることにあります。
もし、あるコンテンツだけ異なる設定をしたいとなった場合に、静的では対応が難しかったためインスタンス生成する形をとりました。
Flasherの方々はなにかしらのライブラリを使用されていると思いますが、もし LiquidLayout 気に入った!となれば使っていただけると幸いです。
また、こうしたほうがいいんじゃない?などご意見いただけるともっと幸いです。
- Comments: 8
- Trackbacks: 2
embedSWFの引数メモ(Progression3.1.2)
- 2009-01-27 (火)
- Progression
Progression3.1.2にアップデートで、SWFObject がバージョン 2.1 にアップデートされたことに伴い progression.js も大きく変更されているようで、embedSWFという関数で表示できるようになっている。
ただ、僕が今現状で作っているサイトで最初に読み込むファイル名を preloader.swf という名前から別のものに変更してしまっており、index.html 内にその記述がどこにもないので、渡すことの出来そうな引数を調べてみたのでメモ。
渡すことの可能な引数と初期値一覧
url:"preloader.swf", replaceElementId:"attention", width:640, height:480, adjustHorizontal:false, adjustVertical:false, centering:true, version:"9.0.45", useExpressInstall:true, flashvars:{}, params:{ bgcolor:"#FFFFFF", wmode:"window", allowfullscreen:true, allowscriptaccess:"samedomain" } attributes:{}
params の中は SWFObjectにそのまま渡されるだけだと思うので、Flashのparam設定が使えると思われます。
http://www.adobe.com/go/tn_12701
- url
読み込みを開始するSWFへのパス - replaceElementId
SWFを表示するHTML要素のID属性名 - width
SWFの横幅(SWFForceSizeの最小幅(?)) - height
SWFの高さ(SWFForceSizeの最小高さ(?)) - adjustHorizontal
横幅100%表示にするかどうか - adjustVertical
高さ100%表示にするかどうか - centering
画面の中央表示をするかどうか(?) - version
Flash Playerのバージョン - useExpressInstall
Express Installを適用するかどうか
(ただし、expressinstall.swfのパスは”contents/scripts/swfobject/expressinstall.swf”で固定のようです。) - flashvars
FlashVars - params
params - attributes
attributes
- Comments: 0
- Trackbacks: 0
Progressionクラスベースオートアップデート
- 2009-01-21 (水)
- Progression
Progressionを3.0.8から3.1.2へやっと先日アップデートしました。
そこで、オートアップデートを使用すると、下記のエラーが発生し失敗。
... 問題が発生したためアップデート処理を中断します。 ... バックアップデータを復元します。 プロジェクトの復元に失敗しました。バックアップデータから手動で復元してください。
プロジェクトフォルダを見てみると、フォルダは存在するもののファイルというファイルがもぬけの殻・・・
エラーログにバックアップデータがあると書いてあるということと、アップデート前に事前にプロジェクトの全バックアップを取っていたのですが、それでも冷や汗が出ました。。
調べてみると、Progression Forumでflabakaさんがオートアップデート機能について情報共有されていて、どうやら現在進行しているプロジェクトはSubVersionで管理していて、それで生成される「.svn」というフォルダがよろしくないことが判明。
flabakaさんのこちらの記事で詳しく説明されてます。
flabaka – libsフォルダにカスタムクラスを入れてると、オートアップデートが使えない!
flabakaさんの記事によると、「.svn」フォルダを全削除すればおkとありますが、プロジェクト自体をSubVersion管理しているのでそうするわけにも行かず、別ディレクトリに新たなプロジェクトを作成(テストプロジェクトなどのアップデートでも可)して、リソースノートとにらめっこしながら「libs」ファイルの中身を上書きという形を取りました。
3.0.8 から 3.1.2 へのアップデートだったので、追加クラス・変更クラスについては上書きで問題ないと思いますが、削除クラスとしては HIGEWheel.as だけかなと思います。
削除:org.libspark.utils.ui.HIGEWheel
↓
追加:org.libspark.ui.SWFWheel
これに伴い /src/libs/org/libspark/utils のフォルダも必要なくなります。
今回の教訓としてはとりあえずなんかするときはバックアップを取っておこうと心に誓いました。
- Comments: 4
- Trackbacks: 1
CastMovieClipを多用しすぎるのも危険?
- 2008-12-18 (木)
- Flash | Progression
こんな生意気なことを言えばtaka:nium様に怒られるかもしれないが、ちょっと先日困ったことが発生したのでアップ。
非常に便利なのでなにかとシンボルを作るときもCastMovieClipを継承したMovieClipを作成しているわけなんですが、先日DataGridのCellRendererのスキンをいじくりたいことがあって、それらもCastMovieClip継承のクラスを作って入れ込んでみた。
そしたら、どうにもこうにも動きがもっさりしている・・・
僕のソースがきっと悪いんだと思って、あれやこれやをコメントアウトしてみるがどうにも改善しない。
それで単純にリンケージの基本クラスだけを変更してみたものでテスト。
- 基本クラス:flash.display.MovieClip
- 基本クラス:jp.progression.casts.CastMovieClip
- 基本クラス:jp.nium.display.ExMovieClip
この3種類を作ってテスト。
Google Chromeのタスクマネージャで確認してみる
そうすると、CastMovieClip・ExMovieClipを継承したほうでは、DataGrid内でマウスを動かしたりスクロールさせたりすると、メモリが増える増える!
普通にMovieClip継承でも増えるんやけど、増え方が尋常じゃない・・・
カラム数が増えると当たり前だけど増え幅も増大する。。
そして一度上がったものは減ってくれない・・・・
もうちょい単純なソースで検証してみる。
ただただENTER_FRAMEで追加削除を繰り返すのみのクラスを作って検証。
生成するものをCastMovieClipかMovieClipかを切り替えて書き出してみる。
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import jp.progression.casts.CastDocument; import jp.progression.casts.CastMovieClip; import jp.progression.Progression; public class AddCastIndex extends CastDocument { public var prog:Progression; public function AddCastIndex() { } protected override function _onInit():void { prog = new Progression( "index", stage ); prog.root.onInit = function():void { var cast:CastMovieClip; var ny:Number = 0; var container:Sprite = new Sprite(); var enterFrame:Function = function( e:Event ):void { if ( cast ) { container.removeChild( cast ); } cast = new CastMovieClip(); cast.graphics.beginFill( 0 ); cast.graphics.drawRect( 0, 0, stageWidth, 20 ); ny = ( ny + 20 ) % stageHeight; cast.y = ny; container.addChild( cast ); } prog.container.addChild( container ); container.addEventListener( Event.ENTER_FRAME, enterFrame ); } prog.goto( prog.firstSceneId ); } } }<
ENTER_FRAME時に一個しか生成しないので、微妙な差だけど、やっぱりCastMovieClipのほうが増加率は高い。
中をまさぐって検証するには敷居が高すぎるのでやめておこう・・・
でもCastMovieClipを使わないなんてもうできない体になっちゃって、そんな世界僕の中にはもうないけど、こういう使い捨てで済むMovieClipやSpriteはCast(Ex)系を継承せずに単純にMovieClipやSpriteを継承するほうがよさそう。
ってゆうのであってるのかな??
- Comments: 0
- Trackbacks: 1
ProcessEvent イベントフローについて(2)
- 2008-11-28 (金)
- ActionScript | Progression
前回のままだと、特殊な使い方すぎてイベントフローの検証になってないので、ユーザーイベントでの遷移に変更して検証。
前回のクラスに移動用ボタンを設置したIndexクラスを作成します。
package { import jp.progression.casts.CastButton; import jp.progression.casts.CastDocument; import jp.progression.commands.AddChild; import jp.progression.commands.Goto; import jp.progression.commands.RemoveChild; import jp.progression.commands.Trace; import jp.progression.Progression; import jp.progression.scenes.SceneId; import jp.progression.scenes.SceneObject; public class Index extends CastDocument { public var prog:Progression; public function Index() { } protected override function _onInit():void { prog = new Progression( "index", stage ); prog.onProcessStart = function() { trace( "onProcessStart :" + prog.eventType ); } prog.onProcessScene = function() { trace( "onProcessScene :" + prog.eventType ); } prog.onProcessComplete = function() { trace( "onProcessComplete :" + prog.eventType + "\n------" ); } prog.onProcessEvent = function() { trace( "onProcessEvent :" + prog.eventType ); } prog.onProcessError = function() { trace( "onProcessError :" + prog.eventType ); } prog.onProcessInterrupt = function() { trace( "onProcessInterrupt :" + prog.eventType + "\n------" ); } var b1:CastButton = new CastButton(); b1.graphics.beginFill( 0xFF0000 ); b1.graphics.drawRect( 0, 0, 100, 100 ); b1.sceneId = new SceneId( "/index/scene2" ); var b2:CastButton = new CastButton(); b2.graphics.beginFill( 0x0000FF ); b2.graphics.drawRect( 0, 0, 100, 100 ); b2.sceneId = new SceneId( "/index/scene3" ); prog.root.addScene( new SceneObject( "scene1", { onLoad: function():void { this.addCommand( new Trace( "scene1 : onLoad" ) ); }, onInit: function():void { this.addCommand( new Trace( "scene1 : onInit" ), new AddChild( prog.container, b1 ) ); }, onGoto: function():void { this.addCommand( new Trace( "scene1 : onGoto" ), new RemoveChild( prog.container, b1 ) ); }, onUnload: function():void { this.addCommand( new Trace( "scene1 : onUnload" ) ); } } ) ); prog.root.addScene( new SceneObject( "scene2", { onLoad: function():void { this.addCommand( new Trace( "scene2 : onLoad" ) ); }, onInit: function():void { this.addCommand( new Trace( "scene2 : onInit" ), new AddChild( prog.container, b2 ) ); }, onGoto: function():void { this.addCommand( new Trace( "scene2 : onGoto" ), new RemoveChild( prog.container, b2 ) ); }, onUnload: function():void { this.addCommand( new Trace( "scene2 : onUnload" ) ); } } ) ); prog.goto( new SceneId( "/index/scene1" ) ); } } }
まず /index/scene1 に行くと赤いボタンが配置され、クリックすると /index/scene2 に飛び青いボタンが表示され、そのボタンをクリックすると設定されていない /index/scene3 に遷移するよう要求しエラーを発生させます。
出力結果
onProcessStart :null onProcessScene :load onProcessEvent :load onProcessEvent :descend onProcessScene :load onProcessEvent :load scene1 : onLoad onProcessEvent :init scene1 : onInit onProcessComplete :init ------ onProcessStart :init onProcessEvent :goto scene1 : onGoto onProcessEvent :unload scene1 : onUnload onProcessScene :load onProcessEvent :load scene2 : onLoad onProcessEvent :init scene2 : onInit onProcessComplete :init ------ onProcessStart :init onProcessEvent :goto scene2 : onGoto onProcessEvent :unload scene2 : onUnload [ERROR] 移動先のシーンが存在しません, 目的地 = /index/scene3 onProcessError :load
scene2 の onInit イベント内で中断実行を行う処理に変更してみる。
onInit: function():void { this.addCommand( new Trace( "scene2 : onInit" ), function():void { this.interrupt(); }, new Trace( "中断実行後" ) ); }<
出力結果
onProcessStart :null onProcessScene :load onProcessEvent :load onProcessEvent :descend onProcessScene :load onProcessEvent :load scene1 : onLoad onProcessEvent :init scene1 : onInit onProcessComplete :init ------ onProcessStart :init onProcessEvent :goto scene1 : onGoto onProcessEvent :unload scene1 : onUnload onProcessScene :load onProcessEvent :load scene2 : onLoad onProcessEvent :init scene2 : onInit 中断実行後 onProcessInterrupt :init ------
interrupt メソッドに引数 true を渡して、強制中断実行に変更するとそのあとの処理は実行されず終了する。
function():void { this.interrupt( true ); }
- onProcessStart で始まり正常終了した場合は onProcessComplete で終わる
- onProcessEvent と SceneObject イベントは対で実行され、onProcessEvent が常に先に実行される
- onProcessScene イベントはシーンに入る直前に実行される
- 階層化されていれば通過シーン到達直前もすべて onProcessScene は実行される
- Comments: 0
- Trackbacks: 0
ProcessEvent イベントフローについて(1)
- 2008-11-27 (木)
- ActionScript | Progression
Sceneでのイベントフローはいろんな方が書いておられるので非常に勉強になりますが、ProcessEventについてはあまり見つけられなかったので、試してみました。
Progressionインスタンスのイベントハンドラメソッドには
- onProcessStart
- onProcessScene
- onProcessComplete
- onProcessEvent
- onProcessError
- onProcessInterrupt
が用意されています。
これがSceneObjectのonLoadやonInitからみてどんなタイミングで実行されるのかテストするために、次のようなIndexクラスを作成します。
package { import jp.progression.casts.CastDocument; import jp.progression.commands.Goto; import jp.progression.commands.Trace; import jp.progression.Progression; import jp.progression.scenes.SceneId; import jp.progression.scenes.SceneObject; public class Index extends CastDocument { public var prog:Progression; public function Index() { } protected override function _onInit():void { prog = new Progression( "index", stage ); prog.onProcessStart = function() { trace( "onProcessStart :" + prog.eventType ); } prog.onProcessScene = function() { trace( "onProcessScene :" + prog.eventType ); } prog.onProcessComplete = function() { trace( "onProcessComplete :" + prog.eventType ); } prog.onProcessEvent = function() { trace( "onProcessEvent :" + prog.eventType ); } prog.onProcessError = function() { trace( "onProcessError :" + prog.eventType ); } prog.onProcessInterrupt = function() { trace( "onProcessInterrupt :" + prog.eventType ); } prog.root.addScene( new SceneObject( "scene1", { onLoad: function():void { this.addCommand( new Trace( "scene1 : onLoad" ) ); }, onInit: function():void { this.addCommand( new Trace( "scene1 : onInit" ), // scene2へ移動 new Goto( new SceneId( "/index/scene2" ) ) ); }, onGoto: function():void { this.addCommand( new Trace( "scene1 : onGoto" ) ); }, onUnload: function():void { this.addCommand( new Trace( "scene1 : onUnload" ) ); } } ) ); prog.root.addScene( new SceneObject( "scene2", { onLoad: function():void { this.addCommand( new Trace( "scene2 : onLoad" ) ); }, onInit: function():void { this.addCommand( new Trace( "scene2 : onInit" ), // 強制的にエラーを発生させる new Goto( new SceneId( "/index/scene3" ) ) ); }, onGoto: function():void { this.addCommand( new Trace( "scene2 : onGoto" ) ); }, onUnload: function():void { this.addCommand( new Trace( "scene2 : onUnload" ) ); } } ) ); prog.goto( new SceneId( "/index/scene1" ) ); } } }
出力結果
onProcessStart :null onProcessScene :load onProcessEvent :load onProcessEvent :descend onProcessScene :load onProcessEvent :load scene1 : onLoad onProcessEvent :init scene1 : onInit onProcessStart :init onProcessEvent :goto scene1 : onGoto onProcessEvent :unload scene1 : onUnload onProcessScene :load onProcessEvent :load scene2 : onLoad onProcessEvent :init scene2 : onInit onProcessStart :init onProcessEvent :goto scene2 : onGoto onProcessEvent :unload scene2 : onUnload [ERROR] 移動先のシーンが存在しません, 目的地 = /index/scene3 onProcessError :load onProcessInterrupt :load onProcessInterrupt :load
想像通りですが、SceneEvent が発生した際には onProcessEvent が実行されてから、シーンの各イベントハンドラが実行されるようです。
ただこの検証だとscene1に到達した瞬間のコマンドリスト内で強制的にscene2へGoToで飛ばしているので、中断実行であるonProcessInterrupt が入ると思っていたんですが、scene1 : onInitの次は onProcessStart :init が実行されてますね。
多分最後に2つ出力されているonProcessInterrupt のどちらかがこれに相当するのでしょうか?
scene1 の onGoto 内に new Wait( 1000 ) のようにWaitコマンドを挟むと、onProcessInterrupt がその時点で出力されます。もしかすると中断実行も非同期処理になっているのかな?
- Comments: 1
- Trackbacks: 0
PreloaderとListenコマンド(2)
- 2008-11-20 (木)
- ActionScript | Progression
前回に引き続き、もう少しだけListenコマンドを触ってみる。
コンテンツに入る前にイントロムービーを流したいなどはよくある話だと思います。
メインコンテンツを長々読み込んだあとに、またイントロ用のローディングなんてのはあまりふつくしくないので、Preloaderでメインコンテンツを読み込む前に流してしまおうというテストです。
ムービーが再生終了した後にメインコンテンツを読み込むようにします。
しかしイントロムービーの場合往々にしてスキップボタンも必要になってくることが多いと思います。
そのどちらものイベントでコマンドを抜けるようにすればいいので、ほかのイベントと干渉しないよう新たにイベントクラスを作ってしまうほうが確実で簡単かと思います。
public class PreloadEvent extends Event { public static const PRELOAD_COMPLETE:String = "preloadComplete"; public function PreloadEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) { super(type, bubbles, cancelable); } public override function clone():Event { return new PreloadEvent(type, bubbles, cancelable); } public override function toString():String { return formatToString("PreloadEvent", "type", "bubbles", "cancelable", "eventPhase"); } }
と、完了イベントを持つイベントクラスを用意して2つのイベントが起こった際に、preloadCompleteを送出するようにします。
private function _introComplete( e:Event ):void { // PreloadEvent.PRELOAD_COMPLETEイベントを送出 dispatchEvent( new PreloadEvent( PreloadEvent.PRELOAD_COMPLETE ) ); } protected override function _onCastLoadStart():void { var player:FLVPlayback = FLVPlayback( getChildByName( "introPlayer" ) ); player.addEventListener( VideoEvent.COMPLETE, _introComplete ); skip.addEventListener( MouseEvent.CLICK, _introComplete ); player.play( "intro.flv" ); addCommand( new Listen( this, PreloadEvent.PRELOAD_COMPLETE, { timeOut: 0 } ), new Trace( "イントロが終了しました" ), new RemoveChild( this, player ), new RemoveChild( this, skip ) ); }
{ timeOut: 0 }は忘れずに。(よく忘れる・・・オデ)
んでテキトーにイントロで使ったものを削除すれば、このあとメインコンテンツのローディングが開始されます。
ムービー再生中にバックグラウンドでメインコンテンツを読み込んだらもっとカコいいけどね。
- Comments: 0
- Trackbacks: 0
PreloaderとListenコマンド(1)
- 2008-11-17 (月)
- ActionScript | Progression
PreloaderクラスはProgression2.0ではExPreloaderを継承していたものが、Progression3.0になって新たにCastPreloaderを継承することとなり大きく変わりましたね。
イベントの流れとしては
_onInit (読み込み完了 / ステージの設定など) ↓ _onCastLoadStart (ロードが開始される直前) ↓ ←登録されたCommandListの全てのコマンドの処理が ↓ 完了すれば次へ [メインSWFの読み込み開始] ↓ _onProgress (プログレスバーの表示など) ↓ _onCastLoadComplete ↓ ←登録されたCommandListの全てのコマンドの処理が ↓ 完了すれば次へ [メインSWFをドキュメントの表示リストに追加]
という流れらしい。
なので以前はロードが開始して読み込み終わるまで止めることのできなかったので、本当にローディングの処理しかできなかったけれど、ロード開始直前とロード完了直後のCommandListにより、幅広い表現ができますね。
たとえば、
「このコンテンツには音声が含まれます。ヘッドフォンのボリューム上げてね」みたいなアテンションとか、「HTML版」「Flash版」みたいな振り分けページがFlashページでできる。
早く見たいときに散々メインコンテンツ読み込んでからでないとHTML版の表示ができないのは本当にストレスですからねぇ。。。
そんなとき使えるのがListenコマンド!
Preloaderとか、ページ遷移の前に規約を読ませるみたいなわざわざScene作るのがめんどくさい時くらいしか使い道が思いつかないListenコマンドw
でも使い出すとすごく便利かもしれない。
Listenコマンドはイベントを送出するdispatcherと受け取りたいイベントの種類の名前を渡すことで、そのイベントが起こるまで待機してくれます。
flashButtonとhtmlButtonというインスタンスがあるとして
protected override function _onCastLoadStart():void { htmlButton.addEventListener( MouseEvent.CLICK, function():void { navigateToURL( new URLRequest( "html.html" ) ); } ); addCommand( [ new AddChild( this, flashButton ), new AddChild( this, htmlButton ) ], new Listen( flashButton, MouseEvent.CLICK, { timeOut: 0 } ), new Trace( "Flash版ボタンがクリックされました" ), [ new RemoveChild( this, flashButton ), new RemoveChild( this, htmlButton ) ] ); }
とすれば、Flash版のボタンを押されたときにのみメインコンテンツのロードを行います。
Listenコマンドを使用する際は、第3引数でtimeOutを”0″にしておかないとデフォルト15秒でCommandTimeOutErrorエラーが発生しコマンドリストが終了します。
(ただ終了しても問題なく動くように見えるんですけどね。。。でもエラーが出るのはいやなので設定必須)
次は複数のlistenerを管理する場合のことについて書いてみます。
- Comments: 0
- Trackbacks: 2
SceneObjectのaddSceneFromXMLについてのメモ
- 2008-11-17 (月)
- ActionScript | Progression
Progression3都物語で勉強してきたことやけど、よく忘れそうなので今になってメモ。
protected override function _onLoad():void { // 実行したいコマンドを登録します。 addCommand( // XML ファイルを読み込みます。 new LoadURL( new URLRequest( "index.xml" ) ), // 匿名関数を実行します。 function():void { // 読み込んだ XML ファイルから子シーンを作成します。 addSceneFromXML( new XML( this.latestData ) ); } ); }
とする際、XMLのcls属性のString型からgetDefinitionByNameでクラスの参照を生成する際に、「クラス名が定義されてないよ」とReferenceErrorを投げ返してきます。
なので、コンストラクタなどで
public function IndexScene( name:String = null, initObject:Object = null ) { // スーパークラスを初期化します。 super( name, initObject ); // クラスが SWF ファイルに含まれるように参照しておきます。 MyScene1; MyScene2; MyScene3; MyScene4; }
という感じで、ただ参照するためにクラス名のみを書いておくとエラーなく動作します。
- Comments: 0
- Trackbacks: 1
ホーム > Progression
- Search
- Feeds
- Meta