[AS]progression4RC departedSceneIdやdestinedSceneIdをif文とかで判定できないってときはここに注意

progressionを使ううえでの便利プロパティ。
departedSceneId
destinedSceneId
以前のエントリでも書いてるように、出発シーンと、到着シーンを取得できます。
ただし↑はprogression3の書き方。
progression4では、progressionインスタンスは無くなり、managerが持ってるプロパティ。


manager.destinedSceneId;
manager.departedSceneId;

これを使って、if文の処理をしたいときちょっとはまったのでメモ。
destinedSceneIdとかdepartedSceneIdをtraceすると、
/indexとか、/index/aboutとか、sceneIdを出力してくれます。
なので、戻り値のデータ型はString?と思いきや、実は違います。


trace(manager.departedSceneId)//出力(例):/index
trace(typeof manager.departedSceneId)//出力:object(stringではない)

なので、if文で判定するときは、↓だと上手く判定されません


//manager.departedSceneId == manager.destinedSceneIdは中身がなんであろうと常にtrueとなる
if(manager.departedSceneId == manager.destinedSceneId){
    //処理
}

traceしたときに見えるSceneId名で判定させる場合は.toString()をつければOK


//
if(manager.departedSceneId.toString() == manager.destinedSceneId.toString()){
    //処理
}

※2010/04/17/16:30追記
コメントにてequals()メソッドというものを教えて頂きました。
こっちの方が簡単ですね。


if(manager.departedSceneId.equals(manager.destinedSceneId)){
	//処理
}

※4のBetaまではtoStringなしでも判定してくれてたような気がするけど、RCからは無いとダメみたい。

[AS]swcでくるんだクラスをgetDefinitionByName()で読み込むときの注意

SWC書き出しでアセット作るというワークフローを試してみたところ、若干はまったのでメモ。

SWCの書き出しと読み込みはkayacさんの記事を参照ください。
参考:SWC書き出しを有効に使って作業効率アップ:_level0.kayac

で、たとえば、MyMc0ってクラス名でリンケージしたMcを含んだswcファイルを用意したとして、
そのMyMc0を取り出すときの処理で、普通に書くと↓な感じでOK


var myMc0:MyMc0 = new MyMc0();
addChild(myMc0);

ただここで、クラス名を動的に生成したい場合は、getDefinitionByName()使わないとなので、こんな感じ。
これも問題なくOK。


var index:int = 0;
var className:String = "MyMc" + index;
var myClass:Class = getDefinitionByName(className) as Class;
//myMc0はMyMc0として定義
var myMc0:MyMc0 = new myClass();
addChild(myMc0);

で、お次はハマったダメな場合の書き方
↓これはエラーになります。


var index:int = 0;
var className:String = "MyMc" + index;
var myClass:Class = getDefinitionByName(className) as Class;
//myMc0はMovieClipとして定義
var myMc0:MovieClip = new myClass();
addChild(myMc0);

違いは、変数myMc0の型をMyMc0とするか、MovieClipにするか、ということ。
MyMc0なら、エラーにはならないけど、MovieClipにするとエラーになります。

MyMc0の親クラスはMovieClipなんだから、間違いないんじゃね?
と思ってましたが、問題はそこではなく、エラーのコードでは、MyMc0が一度も出てきてない、という事実が問題。
もっと具体的にいうと、「MyMc0に参照が通ってないからMyMc0は使えない」、ということになるんだそうだ。

詳細は以下、

コンパイルする段階で、使われてないクラスは含まないようにして最適化されるからですよん。なので import しただけだと、使ってないとみなされて、コンパイル段階で省かれてしまうんです。
必要なのはクラス名ではなくて、クラスへの参照です。なので、ロジック中にクラス書くと、エラー回避出来るんです。

soundkitchen:Tweet1
soundkitchen:Tweet2

なので、エラーコードを修正例としては、


//MyMc0を明示的に表記することで参照を通して、MyMcを使うよってことをアピール。
MyMc0;
//上の書き方がよくわからなくて気持ち悪いときは、空の変数定義でもOK
var hoge:MyMc0;
var index:int = 0;
var className:String = "MyMc" + index;
var myClass:Class = getDefinitionByName(className) as Class;
//myMc0はMovieClipとして定義
var myMc0:MovieClip = new myClass();
addChild(myMc0);

個人的な感覚としては、 getDefinitionByName()でクラス作って、そのクラスでnewしてるんだから、問題ないんじゃない?と思ってたけど、プログラム的には明示的に参照を通さないとだめらしい。

Twitterのおかげで知識が広がる、嬉しい限り。

ちなみにswcを使いたかったのはFlexBuilderとかFlashDevelop+flexSDKで製作するようにしたかったから。
ムービープレビューが速い速い。

[AS]DisplayObjectContainerが内包しているDisplayObjectをすべてremoveChildする

人のソースからのメモ
DisplayObjectContainerが内包しているDisplayObjectをすべてremoveする処理を1行で。
whileは無限ループになるのが怖いから苦手意識あるなー


while(numChildren) removeChildAt(0);

[AS]フォント名を指定するときの注意(日本語?英語?)

一個前の記事でも書いたのだけど、

※ここで引っかかったのはフォントの指定。
フォント名を指定するときに、flashのヒストリパネルに表示されるjsflをそのまま使ったらフォントが反映されない。
たとえば、新ゴProのLを指定したいときには、
jsflには、setElementTextAttr(‘face’,’ShinGoPro-Light’);と表示されたのでそのままコピペしたら動作しない。
フォント名を取得するサンプルで取得したフォント名を使用すると上手くいった。
setElementTextAttr(‘face’,’A-OTF 新ゴ Pro L’);ってな感じになります。
この差異の原因はFlashが日本語版か英語版かってことなのかな、まぁよくわからん。

この現象は予想通りコンパイラに依存するっぽい。
FlashDevelop + Flex4SDKBeta1の組み合わせて、フォント指定でパブリッシュしてみると、
指定した、フォント名が、
A-OTF 新ゴ Pro Lでは反映されずに、
ShinGoPro-Lightだと反映された。

Flex4SDKは日本語仕様ではないから、日本語は認識しないのだね。
この辺は無理に日本語化しないでアルファベットに統一してくれたらわかりやすいと思うんだが。。。

[JSFL]シンボル内の静止テキストのサイズ、フォントを変更するJSFL

製作経緯はこんなかんじ。
e-ラーニング系のコンテンツをタイムラインのアニメーションで製作中のこと。
静止テキストのモーショントゥイーンを大量にステージ配置。
雛形できたら大量生産するぜー、と5ファイルくらい作ってたところで、ここにきてテキスト関係の仕様の提示。
OH MY GOD(ってかちゃんと確認しないで作り始めたボクが悪い)
フォントサイズの変更、フォント色の変更、フォントの変更。。。
1個1個MCの中に入って静止テキストを変更するのめんどくさい。。。
1ファイルあたりMCが10個以上あるし。。。
!そうだ!これ、JSFLでできるんじゃね!?
とこんな感じ。

というわけで以前作ったソースをちょろっと変更してできたのはこんな感じ。
使い方
色を変更したいMCをライブラリで選択し(複数OK)、コマンドを実行。
それぞれ値を入力するダイアログがでるので値を入力すればOK。
※内部にテキストフィールドが1個だけあるようなシンボルの変更を想定してますのでそれ以外はどうなるかわかりません。。。

◆フォントサイズ変更


var doc = fl.getDocumentDOM();
var num = prompt("フォントサイズを入力", "18");

var items = doc.library.getSelectedItems();
for (var i = 0; i < items.length; i++) {
	doc.library.editItem(items[i].name);
	doc.selectAll();
	doc.setElementTextAttr('size',num);
	doc.exitEditMode();
}

◆フォント変更


var doc = fl.getDocumentDOM();
var fontName =  prompt("フォントを指定", "A-OTF 新ゴ Pro L");

var items = doc.library.getSelectedItems();
for (var i = 0; i < items.length; i++) {
	doc.library.editItem(items[i].name);
	doc.selectAll();
	doc.setElementTextAttr('face',fontName);
	doc.exitEditMode();
}

※ここで引っかかったのはフォントの指定。
フォント名を指定するときに、flashのヒストリパネルに表示されるjsflをそのまま使ったらフォントが反映されない。
たとえば、新ゴProのLを指定したいときには、
jsflには、setElementTextAttr(‘face’,'ShinGoPro-Light’);と表示されたのでそのままコピペしたら動作しない。
フォント名を取得するサンプルで取得したフォント名を使用すると上手くいった。
setElementTextAttr(‘face’,'A-OTF 新ゴ Pro L’);ってな感じになります。
この差異の原因はFlashが日本語版か英語版かってことなのかな、まぁよくわからん。

おまけ
色と、フォントと、サイズをいっぺんに変更できるやつ

◆いろいろいっぺんに変更


var doc = fl.getDocumentDOM();
var num = prompt("フォントサイズを入力", "18");
var fontName =  prompt("フォントを指定", "A-OTF 新ゴ Pro L");
var color = prompt("テキストの文字色を入力", "#000000");
var items = doc.library.getSelectedItems();
for (var i = 0; i < items.length; i++) {
	doc.library.editItem(items[i].name);
	doc.selectAll();
	//サイズ変更
	doc.setElementTextAttr('size',num);
	//フォント変更
	doc.setElementTextAttr('face',fontName);
	//色変更
	doc.setFillColor(color);
	doc.exitEditMode();
}

一応、一式ダウンロードはこちら

[JSFL]シンボル内のオブジェクトの色を一括で変更するコマンド

製作経緯はこんなかんじ。
e-ラーニング系のコンテンツをタイムラインのアニメーションで製作中のこと。
静止テキストのモーショントゥイーンを大量にステージ配置。
あれ。。。よく確認してみたら仕様と違う。。。テキストの色間違ってるじゃん。。。
もう3ファイルくらい作ってて、静止テキストをラップしたMCが大量にあるよ。。。
1個1個MCの中に入って静止テキストの色を変更するのめんどくさい。。。
1ファイルあたりMCが10個以上あるし。。。
!そうだ!これ、JSFLでできるんじゃね!?
とこんな感じ。

そしてできたのはこんなかんじ。
使い方
色を変更したいMCをライブラリで選択し(複数OK)、コマンドを実行。
色を入力するダイアログがでるので色値を入力すればOK。
※MCだけじゃなくて、グラフィックとかボタンでもOK。
※静止テキストだけじゃなくて、シェイプの色も変わります。


var doc = fl.getDocumentDOM();
var items = doc.library.getSelectedItems();
ret = prompt("テキストの文字色を入力", "#000000");
//alert(ret);
for (var i = 0; i < items.length; i++) {
  doc.library.editItem(items[i].name);
  doc.selectAll();
  doc.setFillColor(ret);
  doc.exitEditMode();
}

当初はステージに配置してあるオブジェクトを選択して選択されたMCの中の色を変更しようとしてたのだけど、どうも上手くいかない。
でも良く考えたらこの動作ってライブラリ内のオブジェクトを変更するのと同じことだからこれでいいや、と。

欲しい人いるかはわからんけど一応zipでおいておこう。
シンボル内のオブジェクトの色変更する.jsfl

[AS]BetweenAS3でMovieClipのタイムラインのフレームをトゥイーンさせる

ここ最近は、Tweener絶ちをして、BetweenAS3マンセーな感じです。
で、Tweenerみたいにむービークリップのタイムラインのトゥイーンってできるのかなと思い軽くググってもサンプルでてこなかったので、Twitterで呟いてみたらできますよと教えてもらいましたー、
さすがー、すげー

トゥイーン対象がMovieClipの場合は、_frameで操作できるとのこと。
Tweenerと同じ感覚で使えますね。
こんな感じです。


import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;

//_mcはタイムラインを持ったMovieClipでステージにおいてあるインスタンス名
BetweenAS3.to(_mc , {_frame:_mc.totalFrames}, 2, Expo.easeOut).play();

[AS]デザインパターン シングルトンパターンの使い方

製作なんてどうせ1人でやるから、Singletonなんて特に決めなくても、自分で覚えてるからいいや、と思ってました。
が、改めて、書籍:ActionScript3.0デザインパターンに書かれているSingletonの基本ソースを見て目からうろこが。。。
Singleton以外のところで感動したのでメモ。
今までのかなり無駄なことをしてたかも。

まずはSingletonクラスの基本ソース


package  {
	/**
	 * ...
	 * @author 393
	 */
	public class SingletonModel{
		//自身をクラスメンバーとすることでどこからでもアクセスできるようにする。
		private static var instance:SingletonModel;

		//SingletonEnforcerを引数とすることで外からインスタンス化をできないように。
		//※ただ、引数にnullを設定すれば外からでもインスタンス化できちゃうけど
		public function SingletonModel(enforcer:SingletonEnforcer) {}

		//このメソッドでSingletonModelのインスタンス(instance)の参照を取れる
		public static function getInstance():SingletonModel{
			//SingletonModel.instanceが生成されてなければ生成してから、
			if (!SingletonModel.instance){
				SingletonModel.instance = new SingletonModel(new SingletonEnforcer());
			}
			//returnでインスタンスを返す
			return SingletonModel.instance;
		}
	}
}
class SingletonEnforcer {}

なにが目からうろこだったかって、自分自身をクラスメンバーとして保持するという方法。
これなら、どこのクラスからでも直接参照が取れるから、インスタンスの参照を持ちまわらなくてもいいのよね。
今までは、データモデルとなるようなクラスを、他のクラスに参照渡しても持ちまわってた。
これは一応上記書籍のMVCパターンを参考にしてたのだけど、MをSingletonにしちゃえば、VとかCをインスタンス化するときにわざわざ参照渡さなくてもいいじゃないのかな。
でも全部そうしちゃったらなんか落とし穴もありそうなきもするけど。
とりあえず、こんど使ってみる。

[AS]progression4 PreloadSWF()を実行するタイミングで「Error: 対象の CastPreloader は準備が完了していないか、すでにコンテンツが読み込まれています。」エラーに注意

タイトルどおりの現象。

※PreloadSWF()については↓の記事がとてもわかりやすいです。
jp.ikekou.blog.Main:Progression 4.0.1 Public Beta 1.3 追加機能① PreloadSWFクラス

で、これを観ながら上記ブログとは少し変えながら試してみたのですが、タイトルのエラー発生。
変更した箇所はatCastLoadStart()の部分で、以下のソース


override protected function atCastLoadStart():void {
	var loaderList:LoaderList = new LoaderList({
		onProgress:function():void{
			trace(this.percent)
		}
	});
	loaderList.addCommand(
        //new PreloadSWF()が遅い
		new LoadSound(new URLRequest("sound/sample.mp3"))
		,new PreloadSWF()
	);
	loaderList.execute();
}

結論から言うと、new PreloadSWF()の書く順番が重要。
↓このように書けばOK


override protected function atCastLoadStart():void {
	var loaderList:LoaderList = new LoaderList({
		onProgress:function():void{
			trace(this.percent)
		}
	});
	loaderList.addCommand(
        //PreloadSWF()が早い
		new PreloadSWF()
		,new LoadSound(new URLRequest("sound/sample.mp3"))
	);
	loaderList.execute();
}

ちなみに参考にしたブログでは、loaderListの処理をatCastLoadStart()のaddCommand()内で行い、そこに追加している。
その際には、new PreloadSWF()の順番は影響はしないようす。


override protected function atCastLoadStart():void {
	addCommand(
		function(){
			var loaderList:LoaderList = new LoaderList({
				onProgress:function():void{
					trace(this.percent)
				}
			});
			loaderList.addCommand(
				//new PreloadSWF()の位置は先でもエラーはでない
				,new PreloadSWF()
				new LoadSound(new URLRequest("sound/sample.mp3"))
			);
			this.parent.addCommand(loaderList);
		}
	);
}

command周りの処理の順番がイマイチちゃんと理解していないから、泥臭く検証しないとわからないのよね。。。
ガッツリ理解しとかないとな。。。

[AS]フォント埋め込みの際のフォント名を取得する方法

以前書いた、
[AS]FlashPlayer10ではTestFieldにアルファ処理可能、あとFlashPlayer9でのフォントの埋め込み方法の詳細
の記事の補足

上の記事では、フォントを指定する際に、TextFormat.fontに指定するフォント名を手動で調べないといけないと書いたけど、ライブラリに登録されたフォントから、さくっと取得することができるようだ。


//フレームアクション
//ライブラリ内のフォントのリンケージ名
var class_name="font1";
var loadedFont:Font = new Font();
var LoadFontClass:Class=ApplicationDomain.currentDomain.getDefinition(class_name) as Class;
Font.registerFont(LoadFontClass);
loadedFont = new LoadFontClass();
//これがTextFormat.fontに指定するフォント名となる。
var font_name=loadedFont.fontName;

//おまけ
//テキストフォーマット
var fmt:TextFormat=new TextFormat();
//フォント名を指定
fmt.font=font_name;
fmt.size = 40;
fmt.bold = false;
//テキストフィールド作成
var tf:TextField=new TextField();
tf.embedFonts=true;
tf.defaultTextFormat=fmt;
tf.text="Test";
//表示
addChild(tf);

教えてくれたサイト:frasio report:[AS3]埋め込みフォントの盲点