はてなから移植


はてなからこちらの新ドメインに移行します。

現状Labsしかありませんので、本ドメインに飛んでも何もありませんが、いずれは整備したいと思っています。新ドメイン、新ブログをよろしくお願いします。

マスクしているオブジェクトを変えるとマスクされているオブジェクトがおかしくなる不思議


再現方法

  1. タイムラインのレイヤー1にマスクしたいオブジェクトを配置する(maskedObjとする)
  2. タイムラインのレイヤー2にマスクするオブジェクトを配置する(maskObj1とする)
  3. レイヤー2をレイヤー1のマスクに設定する
  4. レイヤー2の適当なフレームに空のキーフレームをうち、別のマスクするオブジェクトを配置する(maskObj2とする)
  5. レイヤー1をレイヤー2のフレーム数まで伸ばす

この状態で、maskedObjに対して、maskObj1にマスクされている時に操作した情報は、マスクがmaskObj2に変わった瞬間に消えるみたいです。普通はremoveしないと消えないようなaddChildしたオブジェクトや、addEventListenerしたイベントがまるっと消えてしまいます。

マスクしているオブジェクトが変わっただけなのに、マスクされているオブジェクトが初期化されてしまうのです。明らかに変です。

FlashCS4でもFlashCS5でもなります。理由は謎です。ちなみにActionScriptから操作した場合は問題ないようです。Flashのタイムラインからマスクをかけた場合は、複数オブジェクトに対してマスクがかけられたりもするので、動作そのものが違うためでしょうか。

「マスクはASで操作する」あるいは「後で付加するあるいは後で付け直す」とすればこのバグを防げるみたいです。

テスト用fla+asファイル

有名なバグだったりするんでしょうか?こんなので何時間も取られてはたまらないですよね。・・・それは金曜日の私ですw

基準点を中心にするJSFLを考える1


普段はアニメーションはTweenerで作っていて、久しぶりにタイムラインでバリバリやる感じのものを作ろうと思い、久しぶりにクラシックトゥイーンなどしてみたんですが、基準点を操作するのがなかなかメンドクサイ。そこでJSFLで何とかならないかと思ったわけです。

作ったのは以下のようなものです。複数選択には対応していません。

var doc = fl.getDocumentDOM();
doc.enterEditMode('inPlace');
var beforeRect = doc.getSelectionRect();
doc.align('vertical center', true);
doc.align('horizontal center', true);
//サイズが奇数値だとセンタリングしたときに端数がでるので調整
var tempRect = doc.getSelectionRect();
var roundX = Math.round(tempRect.left) - tempRect.left;
var roundY = Math.round(tempRect.top) - tempRect.top;
roundX = Math.round(roundX * 10) / 10;
roundY = Math.round(roundY * 10) / 10;
doc.moveSelectionBy({x:roundX, y:roundY});
var afterRect = doc.getSelectionRect();
var moveX = Math.round(beforeRect.left - afterRect.left);
var moveY = Math.round(beforeRect.top - afterRect.top);
doc.exitEditMode();
doc.moveSelectionBy({x:moveX, y:moveY});
doc.setTransformationPoint({x:0, y:0});

とりあえずはシェイプ1つ置いたものならば、基準点と変形点を真ん中に変更できました。

作ってみて気になったのは、getSelectionRectで取得できるRectangle.leftやRectangle.topの値が、100.499など、中途半端な値になってしまうこと。

置き方が悪いのかといろいろやってみましたが、上手くいかないようなので、四捨五入しました。

次はこれをもうちょっと使い易くしてみようと思います。

カスタムクラスのインスタンスをtraceした時に配列のように内容を出力したい


久々に。仕事がてんてこまいだったのがようやく落ち着いてきました。

表題の件、ずっとできるはず、と思いながらうまく行かなかったのですが、ある時ふと思い立って調べ直してみたらうまく行ったのでメモ。

SpriteやMovieClipを拡張して作るときは、toString()をoverrideして、戻り値を書き出したい値にすればできる様子。

ただ、Objectを拡張しただけのクラス(何もextendsしてないクラス)だとこれだとできない。

Error: Method marked override must override another method.

みたいに怒られます。

どうしたらいいものかと思ってたんですが、直に

public class Hoge {
    public var name:String;
    public var text:String;
    public function toString():String {
        return '['+[name, text]+']';
    }
}

と書けばちゃんとtraceした時にtoStringとして動作するようです。いろいろ調べてみたらtoStringはObjectのObject.prototype.toStringとして書かれているというような記述がありました。

参考:Adobe ActionScript 3.0 * 高度なトピック

真似してみたらこれでもできた。

public class Hoge {
    public var name:String;
    public var text:String;
    prototype.toString = function():String {
        return '['+[this.name, this.text]+']';
    }
}
//----------
var hoge:Hoge = new Hoge();
hoge.name = 'nameTest';
hoge.text = 'textTest';
trace(hoge);  //[nameTest,textTest]

prototypeオブジェクトについてもうちょっと調べてみようと思います。

パブリッシュする時に一緒にtrace文を省略した上で最適化保存してくれるJSFL


あったら便利かなと言うことで作ってみました。

var doc = fl.getDocumentDOM();
var profileXML = doc.exportPublishProfileString();
var newProfile = profileXML.replace("0", "1");
doc.importPublishProfileString(newProfile);
doc.publish();
doc.importPublishProfileString(profileXML);
doc.saveAndCompact();

こちらショートカットに登録すると便利に使えます。・・・使えるんですが、ショートカットを登録してもFlashを起動しただけだとショートカットが有効にならず、必ず1回キーボードショートカットのウィンドウを開かないとできない・・・。何故・・・。

下は開いているflaファイル全てに対して実行できるようにしたもの。

if (fl.documents.length > 0){
    for (i=fl.documents.length-1; i>=0; i--){
        cleanPublish(fl.documents[i]);
    }
}
else{
    fl.trace("ドキュメントが開かれていません。");
}
function cleanPublish(doc){
    fl.setActiveWindow(doc);
    var profileXML = doc.exportPublishProfileString();
    var newProfile = profileXML.replace("<OmitTraceActions>0</OmitTraceActions>", "<OmitTraceActions>1</OmitTraceActions>");
    doc.importPublishProfileString(newProfile);
    doc.publish();
    doc.importPublishProfileString(profileXML);
    doc.saveAndCompact();
}

最初はただ単にfl.documents[i]を関数に渡しただけでできるものかと思ったんですが、こちらと同じ罠に引っかかりました。

http://level0.kayac.com/2009/08/flatrace.php

対処法はいくつか試したんですが、

fl.setActiveWindow(doc);

でOKじゃないかと思います。これで現在開いているドキュメントをアクティブにできるので、fl.documents[i]が選択された状態になり、ドキュメントのプロパティも新しいものが選択されるはずです。

失敗したときは書き出し先が上書きされるという恐ろしい事態になったので、作るときは注意しないとですね。

ちなみに上のスクリプトのご利用は自己判断でご自由にどうぞ。

パッケージ名を自動で全部書き換えてくれるJSFLがあったら便利そう。ただ、JSFLでやる意味はあるのか、という疑問もありますね。ライブラリ内のものは除いて。

flFile.runCommandLine()

を使うとコマンドラインに命令を出せるようなので、こちらからテキスト編集プログラムを実行させた方が早いかもしれないですね。