2010年7月23日 星期五

使用FlashDevelop來幫自定義的Library產生SWC、ASDoc、以及Fat SWC

Flash程式開發一段時間後,相信大家多少都會開發自己常用功能的Library來使用。一開始當然要先產出source code,一堆.as檔案依照package分別放在適合的資料夾裡。慢慢的,我們可能會想把這一堆檔案包裝成一個SWC檔,不但輕巧方便,也比較快速。現在大部分的Libraries都有提供SWC檔。隨著我們自定義的功能與類別越來越多,我們可能會希望產出一份說明文件,一方面提醒自己,另一方面也讓工作夥伴方便了解這些Lib.的功能,如果要公布出來給大家使用,那就更不可或缺啦。最常見的文件格式,就是ASDoc,也就是如ActionScript 3.0 Client Library for Facebook Platform API,或者Adobe自己官方的ActionScript 3.0 Reference for the Adobe Flash Platform,相信這樣的文件大家並不陌生。這些html當然不是人工刻出來的,只要在source code裡面依照一定的規則加上註解,再經由工具就可以產出。不管是SWC或者ASDoc都有一點歷史了,這篇最主要還要介紹新一點的東西--Fat SWC。從Flash Builder 4開始,code hint不再只有參數的型別,而是連同ASDoc裡的說明都會自動跑出來,減少了程式寫到一半還要去查說明文件的機會。FlashDevelop最新的版本也已經支援,不過我們所使用的Libraries的SWC必須是Fat SWC,也就是包了ASDoc產出的一些XML檔案進去的SWC,這樣開發工具才能把註解抓出來顯示在code hint裡。下面就一項一項來說明如何用FlashDevelop來幫我們產出。

用FlashDevelop產出SWC
首先,前置作業要先做好。除了裝好FlashDevelop以外,Flex SDK以及Java 1.6也要裝好,可參考這篇。Java 1.6裝好後,還要設定好電腦的環境變數:電腦->內容->進階系統設定->進階->環境變數,找到一個path的變數,按編輯,在最後面加上如;D:\Program Files\Java\jdk1.6.0_21\bin這樣的路徑,依照Java安裝的路徑,最前面用分號跟前面的內容隔開。這些一定要做好才能產生SWC與ASDoc。

確定都裝好後,FlashDevelop還要安裝一個PlugIn: ExportSWC。安裝好重開FlashDevelop,可以看到工具列上多了一個紅色的Icon,那就成功了。

ExportSWC2.0已經出了(看時間好像是25天前),上面的下載網址也更新了,之前安裝過的朋友請將Plugin資料夾裡的ExportSWC.dll刪掉,下載ExportSWC2.0.fdz後點兩下就會自動幫我們解壓縮到Plugin資料夾裡面了。感謝奶綠茶的分享。
接著我們就用FlashDevelop開一個新的AS3 Project,如果有自動產生src/Main.as檔案的話可以直接把它刪掉。接著就在/src底下建立我們Library的package資料夾,例如我現在要建一個grayliao.test的package,然後在底下開一個新的TestText Class,功能很簡單,就是自動加個TextField到場景上而已。建構式可以傳入一個字串顯示在這個TextField裡面。另外寫一個setText方法,一樣可以接收一個字串修改文字內容。有時候,我們開發的Library會用到其他第三方的Library,或者我們可能有一個package就是專門擴充某個別人寫的Lib.的功能。因此我們這裡就故意把as3corelib的SWC放入/lib資料夾裡,記得在Project視窗這個檔案上面按右鍵,勾選Add To Library,編譯時才不會出錯。而我們的TestText 裡面故意import這個Lib.裡的JPGEncoder,然後在程式裡也new一個JPGEncoder實體,但只是為了測試,並沒有真的想做啥。另外為了幫ASDoc的內容鋪路,我們也順便加上一些註解,註解的加法可以參考官方文件,或者找一些有提供source code的Lib.來參考。原始碼順便貼一下:
/**
 * Test Library
 * 
 * @author Gray Liao
 * @version 1.0.0
 * @see http://grayliao.blogspot.com/
 * 
 * 這是一個測試用的Library。
 */
package grayliao.test 
{
  import flash.display.Sprite;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;

  import com.adobe.images.JPGEncoder;

  /**
   * 測試用的測試文字類別。
   */
  public class TestText extends Sprite
  {
    private var _tf:TextField;
    private var _text:String;
    private var _jpgEncoder:JPGEncoder;

    /**
     * 建立新的TestText實體。
     * 
     * @param text
     * 設定文字。
     */
    public function TestText(text:String = "") 
    {
      super();
      _tf = new TextField();
      _tf.autoSize = TextFieldAutoSize.LEFT;
      _tf.text = text;
      addChild(_tf);
      _jpgEncoder = new JPGEncoder(80);
    }
  
    /**
     * 重新設定文字內容的方法。
     * 
     * @param text
     * 設定文字。
     */
    public function setText(text:String = ""):void
    {
      _tf.text = text;
    }
  }
}
要特別注意除了建構式以外,每個function都要指定回傳的型別,沒有回傳值也要指定void。好了之後按下ExportSWC那個紅色Icon,預設在bin資料夾裡面就會幫我們產出跟Project同名的SWC了。
若已更新到ExportSWC2.0的話,它多了一個新功能,按一下紅色Icon旁邊的小三角型展開選單,點選Configure,可以看到右上方多了一個Integrate AsDoc,預設已經勾選了,不用動它。

此時如果註解都已經依照格式下好了,那麼產出來的SWC就已經是Fat SWC了。.swc檔基本上就是一個.zip檔,我們把產出的SWC副檔名改成.zip檔,解壓縮來看,舊版產出來的SWC裡面只有catalog.xml跟library.swf,ExportSWC2.0則會順便產出一個docs資料夾,裡面有ASDoc的XML檔案。

來看看一般SWC與Fat SWC的Code hint有甚麼不一樣:
一般SWC

Fat SWC

Fat SWC會幫們把註解也顯示在code hint裡,這樣就可以減少查閱ASDoc的次數了。


用FlashDevelop產出ASDoc
接著來產生ASDoc。在剛剛的原始碼裡面,我們已經幫類別、建構式、以及setText這個方法加上註解了,上面也提過註解的格式請參考官方文件,這邊就不多花篇幅去講。接著開啟Tools->Flash Tools->Documentation Generator...就會彈出對話視窗:

首先會在Project頁籤裡:
Compiler:右下角的Compiler先選擇ASDOC (AS3)。
Page title:設定產出文件的標題,可以給個響亮的名字。
Exclude classes:要排除的類別。如果某些類別不想產出文件,例如一些只會讓其他類別使用,而不是真正讓user可以去使用的類別就可以一個一個加進來。要填完整的package路徑,每一個以空白鍵隔開。如果是要排除第三方Lib.的話,一個一個排除會很累,等等會介紹其他方法。這邊我們沒有要排除的class,所以就讓它空白。
Output directory:我們在Project資料夾底下開一個docs資料夾來放輸出的文件。
Classpaths:指定要包的class的資料夾,包含有引用的其他Lib.。指定的資料夾底下的子資料夾裡的檔案也都會被找到。但我們要用另一個方法來指定檔案,所以這邊也先空白。
Extra options:ASDoc本身是個指令式的工具,而這邊就可以將要執行的指令輸入。指令以"-"開頭,一個空白鍵後接參數,每個指令中間再以空白鍵隔開。指令也可以在官方文件裡查到,在這邊先介紹要使用到的三個指令:
-source-path:指定原始碼的路徑。我們把原始碼放在src資料夾裡,所以後面參數要給它./src。
-doc-sources:文件來源,這裡跟原始碼的位置是一樣的,所以也要給./src。只有設定-source-path是不行的。另外有個-doc-classes是一個一個class加進來,輸入完整package路徑,每個class中間以空白鍵隔開,無法使用*將某package下的class都指定進來。因為太累,所以使用-doc-sources一次加。不過比較這兩個就可以比較清楚為什麼除了-source-path還要設定-doc-sources,一個是檔案路徑,一個是類別路徑。
-library-path:其他library的路徑。例如我們剛剛有使用到as3corelib,並且放在lib資料夾裡,所以這邊給它./lib。
目前先單純產出ASDoc,所以一般使用這三個指令就夠了。等等要產出XML給Fat SWC時再回來介紹另外兩個。至於排除第三方Lib.的文件很簡單:只要是使用SWC的Lib.都不會產出文件。所以我們等於也排除完了。雖然有另外一個指令-exclude-dependencies=true,但它跟-doc-classes不能同時使用,因為工具會搞不清哪些該排除,哪些不該排除吧,所以要排除的第三方Lib.就用SWC,若是自定義的某幾個Class想排除就列在Exclude classes裡,或者文件裡用@private。
完整的指令貼在下面:
-source-path ./src -doc-sources ./src -library-path ./lib

接著切換到Settings頁籤:

AS2API location:不要去動它。
ASDoc location:這裡要輸入Flex SDK的bin資料夾路徑,例如我的是:D:\Program Files\flex_sdk_4.1\bin。
然後可以按Save Settings儲存這個頁籤的設定。接著按Save Project...幫這整個設定存成一個.docproj檔,當下次要更新時按Open Project...可以再次叫出來。

都設定完後就按下Generate!,過段時間會跳到Output頁籤,若有錯誤會顯示錯誤,沒錯誤的話會告訴你文件已經產生在docs資料夾了。到docs資料夾點index.html就可以看到我們的ASDoc了!雖然裡面只有一個簡單的Class。


合併產出Fat SWC
因為前面提到ExportSWC2.0產出的SWC已經是Fat SWC了,所以以下的內容就不需要參考了。
最後一步,我們希望code hint裡面除了提示參數的型別外能更進一步提供ASDoc裡寫入的註解,減少我們重覆翻閱文件的次數。先來看看一般SWC與Fat SWC的Code hint有甚麼不一樣:
一般SWC

Fat SWC

了解Fat SWC的用處之後,我們來看看要怎樣產生它。首先回到FlashDevelop的Documentation Generator,如果已經關掉了請用Open Project...將上次存檔開啟。接著在Project頁籤裡的Extra options,我們要再加入另外兩個指令:
-keep-xml=true:將上這個指令會幫我們產出Fat SWC需要用的XML檔案。
-skip-xsl=true:加了上一個指令後,也會同時產生很多用不到的XSL檔案,加上這個指令可以濾掉。不過這個指令加上去後似乎也會讓html文件產不出來,所以我會分兩個步驟:先用之前三個指令產生文件檔案,在加上這兩個指令產出XML。
加上這兩個後的完整指令:
-source-path ./src -doc-sources ./src -library-path ./lib -keep-xml=true -skip-xsl=true
加完後可以Save Project...存檔下來。然後按Generate!就可以看到docs資料夾多了tempdita資料夾以及toplevel.xml。我們等等再回來。
接著到bin資料夾找到之前產出的SWC,其實SWC是個zip壓縮檔,我們把它的副檔名改成.zip,然後解壓縮它,可以看到裡面只有兩個檔案:catalog.xml以及library.swf。我們在裡面新增一個docs資料夾,然後我們回到剛剛的文件資料夾裡面,tempdita資料底下有個grayliao.test.xml,基本上要把檔名像是package路徑的XML檔案都複製起來,我們這個範例只有一個,然後回到我們解壓縮的檔案,剛剛新增的docs資料夾,把XML檔案貼進去。總之檔案架構調整成如下圖:

好了之後我們再把catalog.xml、library.swf以及docs資料夾重新壓縮成zip檔,注意不要產生多的資料夾層級,然後再將副檔名改回swc就可以了。當然比較快速的做法是把docs資料夾整理好,拉進第一次的zip檔裡面,也不用解壓縮後又再次壓縮了。

開一個新專案來測試,果然新的SWC會提供更多的code hint了。耶~~


小小結論:由於自定義的SWC有包到其他Lib.部分的Class,可以在FlashDevelop的Project視窗,點SWC前面的+展開來,Classes裡面有我們包到的JPGEncoder,以及它引用到的BitString。在開發時我們會把自定義以及第三方的SWC都丟到lib裡面供專案使用,只要自定義包的跟第三方Lib.是同一個版本,就不用怕真正引用時會出錯了。

14 則留言:

  1. 整個跟著你的教學做完一次,才發現, ExportSWC2.0
    就經已有了這個功能,只要打勾後,會自動將swc包說明檔。
    可以到這兒下載
    http://sourceforge.net/projects/exportswc/

    回覆刪除
  2. 喔喔!!我來試用一下,再來調整流程。感謝分享!

    回覆刪除
  3. 因為 Away3D 沒釋出SWC,就試著打包看看,中間只Error一次,說有傳入變數沒賦予型別,例 function xxx(a = false) 改成 (a:Boolean = false) 就可以了。

    回覆刪除
  4. 感謝分享。

    我Export出來的fat swc,在FlashBuilder4下有code hint,但是在FD下仍然沒有code hint,用winrar解開swc內也是有產出doc資料夾,使用的FD為3.3.4RTM,ExportSWC為2.3,想請問有人有跟我一樣的問題嗎?

    回覆刪除
  5. Flash IDE可以對class作個別匯出也可以一次全部匯出, 但FD搭exportSWC要如何對個別的class作匯出呢?

    回覆刪除
  6. To Focus1921:
    最近又試了一下,似乎是FD的問題,有時會跑出來,有時不會,用ExportSWC2.0也一樣

    回覆刪除
  7. To jn:
    依照這篇的步驟,src裡面只放一個class就可以了。但我想這麼做應該沒啥意義,應該是要看你為何只想將一個class匯出成swc?在Flash IDE裡面,可以單獨匯出某個元件成SWC提供多個檔案使用,所以這樣做有意義;在FlashDevelop單獨對一個class as檔匯出成swc似乎沒有啥意義?

    回覆刪除
  8. exportSWC似乎會掃瞄整個project中所有的class, 所以匯出的swc中會包含像Main, Preloader這樣的Document Class(lib中的class也會一起包進去), 有時候我們會只想將src底下自己開發的class包進swc, 但不想連Document Class或第三方類庫一起包進去, 又不想每次匯出都要先把不需要包進swc的class移出project資料夾

    回覆刪除
  9. To jn:
    我的做法是開一個乾淨的Project專門放要包成swc的class,砍掉Main這些不要的檔案,每次要包swc才把檔案丟進來。不建議對開發中的Project重複去做包swc的動作

    回覆刪除
  10. 感謝建議, 不過如果exportSWC也有類似 -exclude-classes 這樣的參數設定就完美了

    回覆刪除
  11. 喔耶成功了,好感動!太感謝了

    回覆刪除
  12. Gray Liao 你好,

    請問您可有試過,將 ExportSWC 產出的SWC檔,再經過 mxi 檔包裝成 mxp?

    以往透過fla匯出的SWC都可以再包成mxp檔,方便安裝,安裝完以後從組件庫直接拖到場景上就可以當成組件使用。但 ExportSWC 產出的SWC檔,就算包成了mxp 檔,拖到場景上卻是空白一片,即使trace該元件也會得到 null 值。感覺就像它根本不存在一樣。

    請問 Gray Liao 或各位前輩們是否有遇到過這個問題?

    感謝!

    回覆刪除