OSDN Git Service

1.105.3-SNAPSHOT版開発開始
authorOlyutorskii <olyutorskii@users.osdn.me>
Tue, 17 May 2011 15:18:21 +0000 (00:18 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Tue, 17 May 2011 15:18:21 +0000 (00:18 +0900)
95 files changed:
.hgignore
CHANGELOG.txt
LICENSE.txt
README.txt
src/main/config/checks.xml
src/main/config/pmdrules.xml
src/main/config/suppressions.xml [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/corelib/I18nText.java
src/main/java/jp/sourceforge/mikutoga/corelib/ListUtil.java
src/main/java/jp/sourceforge/mikutoga/corelib/SerialNumbered.java
src/main/java/jp/sourceforge/mikutoga/corelib/WinFile.java
src/main/java/jp/sourceforge/mikutoga/corelib/package-info.java
src/main/java/jp/sourceforge/mikutoga/parser/CommonParser.java
src/main/java/jp/sourceforge/mikutoga/parser/LoopHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/MmdEofException.java
src/main/java/jp/sourceforge/mikutoga/parser/MmdFormatException.java
src/main/java/jp/sourceforge/mikutoga/parser/MmdSource.java
src/main/java/jp/sourceforge/mikutoga/parser/ParseStage.java
src/main/java/jp/sourceforge/mikutoga/parser/package-info.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdBasicHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdBoneHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdEngHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdJointHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdLimits.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdMaterialHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdMorphHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdParser.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdParserBase.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdParserExt1.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdParserExt2.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdParserExt3.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdRigidHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdShapeHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/PmdToonHandler.java
src/main/java/jp/sourceforge/mikutoga/parser/pmd/package-info.java
src/main/java/jp/sourceforge/mikutoga/pmd/BoneGroup.java
src/main/java/jp/sourceforge/mikutoga/pmd/BoneInfo.java
src/main/java/jp/sourceforge/mikutoga/pmd/BoneType.java
src/main/java/jp/sourceforge/mikutoga/pmd/Deg3d.java
src/main/java/jp/sourceforge/mikutoga/pmd/DynamicsInfo.java
src/main/java/jp/sourceforge/mikutoga/pmd/IKChain.java
src/main/java/jp/sourceforge/mikutoga/pmd/JointInfo.java
src/main/java/jp/sourceforge/mikutoga/pmd/Material.java
src/main/java/jp/sourceforge/mikutoga/pmd/MorphPart.java
src/main/java/jp/sourceforge/mikutoga/pmd/MorphType.java
src/main/java/jp/sourceforge/mikutoga/pmd/MorphVertex.java
src/main/java/jp/sourceforge/mikutoga/pmd/PmdModel.java
src/main/java/jp/sourceforge/mikutoga/pmd/Pos2d.java
src/main/java/jp/sourceforge/mikutoga/pmd/Pos3d.java
src/main/java/jp/sourceforge/mikutoga/pmd/Rad3d.java
src/main/java/jp/sourceforge/mikutoga/pmd/RigidBehaviorType.java
src/main/java/jp/sourceforge/mikutoga/pmd/RigidGroup.java
src/main/java/jp/sourceforge/mikutoga/pmd/RigidInfo.java
src/main/java/jp/sourceforge/mikutoga/pmd/RigidShape.java
src/main/java/jp/sourceforge/mikutoga/pmd/RigidShapeType.java
src/main/java/jp/sourceforge/mikutoga/pmd/ShadeInfo.java
src/main/java/jp/sourceforge/mikutoga/pmd/Surface.java
src/main/java/jp/sourceforge/mikutoga/pmd/ToonMap.java
src/main/java/jp/sourceforge/mikutoga/pmd/TripletRange.java
src/main/java/jp/sourceforge/mikutoga/pmd/Vec3d.java
src/main/java/jp/sourceforge/mikutoga/pmd/Vertex.java
src/main/java/jp/sourceforge/mikutoga/pmd/package-info.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/AbstractExporter.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/IllegalPmdException.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/IllegalPmdTextException.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/PmdExporter.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/PmdExporterBase.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/PmdExporterExt1.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/PmdExporterExt2.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/PmdExporterExt3.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdexporter/package-info.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/BoneBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/JointBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/MaterialBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/MorphBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/PmdLoader.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/RigidBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/ShapeBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/TextBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/ToonBuilder.java
src/main/java/jp/sourceforge/mikutoga/pmd/pmdloader/package-info.java
src/main/java/jp/sourceforge/mikutoga/pmd/xml/PmdXmlExporter.java
src/main/java/jp/sourceforge/mikutoga/pmd/xml/PmdXmlResources.java
src/main/java/jp/sourceforge/mikutoga/pmd/xml/Xml2PmdLoader.java
src/main/java/jp/sourceforge/mikutoga/pmd/xml/package-info.java
src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java
src/main/java/jp/sourceforge/mikutoga/xml/DomUtils.java
src/main/java/jp/sourceforge/mikutoga/xml/TogaXmlException.java
src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java
src/main/java/jp/sourceforge/mikutoga/xml/package-info.java
src/main/resources/jp/sourceforge/mikutoga/pmd/xml/resources/pmdxml-101009.dtd
src/test/java/jp/sourceforge/mikutoga/parser/ParseStageTest.java
src/test/java/jp/sourceforge/mikutoga/pmd/MorphTypeTest.java
src/test/java/sample/pmd/DummyHandler.java
src/test/java/sample/pmd/DummyMain.java

index 247007c..7454a09 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -1,3 +1,12 @@
-^nbactions\.xml$\r
+syntax: regexp\r
+\r
+\.orig$\r
+\.orig\..*$\r
+\.chg\..*$\r
+\.rej$\r
+\.conflict\~$\r
+^maven-build\.properties$\r
+^maven-build\.xml$\r
 ^nb-configuration\.xml$\r
 ^nb-configuration\.xml$\r
+^nbactions\.xml$\r
 ^target$\r
 ^target$\r
index 48d1702..1f4333c 100644 (file)
@@ -1,16 +1,16 @@
-[UTF-8 Japanese]\r
-\r
-\r
-TogaGem 変更履歴\r
-\r
-\r
-1.105.2 (2010-10-09)\r
-    ・接続ボーンを持たない剛体のサポート。\r
-\r
-1.104.2 (2010-10-07)\r
-    ・TogaParser1.103.2版を吸収する形で開発を再スタート。\r
-    ・PMDファイルの読み書きに対処。\r
-    ・XML版モデルデータの読み書きに対処。\r
-\r
-\r
---- EOF ---\r
+[UTF-8 Japanese]
+
+
+TogaGem 変更履歴
+
+
+1.105.2 (2010-10-09)
+    ・接続ボーンを持たない剛体のサポート。
+
+1.104.2 (2010-10-07)
+    ・TogaParser1.103.2版を吸収する形で開発を再スタート。
+    ・PMDファイルの読み書きに対処。
+    ・XML版モデルデータの読み書きに対処。
+
+
+--- EOF ---
index 225e3e3..4769031 100644 (file)
@@ -1,34 +1,34 @@
-[UTF-8 English & Japanese]\r
-\r
-The MIT License\r
-\r
-\r
-Copyright(c) 2010 olyutorskii\r
-\r
-\r
-Permission is hereby granted, free of charge, to any person obtaining a copy\r
-of this software and associated documentation files (the "Software"), to deal\r
-in the Software without restriction, including without limitation the rights\r
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-copies of the Software, and to permit persons to whom the Software is\r
-furnished to do so, subject to the following conditions:\r
-\r
-The above copyright notice and this permission notice shall be included in\r
-all copies or substantial portions of the Software.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-THE SOFTWARE.\r
-\r
-\r
-TogaGemオリジナル制作者自身からのコメント:\r
-\r
-  ※ 少なくともこのソフトウェアの実行、複製、配布、改造は自由です。\r
-  ※ 少なくともこのソフトウェアは無保証です。\r
-\r
-\r
---- EOF ---\r
+[UTF-8 English & Japanese]
+
+The MIT License
+
+
+Copyright(c) 2010 olyutorskii
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+TogaGemオリジナル制作者自身からのコメント:
+
+  ※ 少なくともこのソフトウェアの実行、複製、配布、改造は自由です。
+  ※ 少なくともこのソフトウェアは無保証です。
+
+
+--- EOF ---
index 1672527..025b2cb 100644 (file)
@@ -1,96 +1,96 @@
-[UTF-8 Japanese]\r
-\r
-                              T o g a G e m\r
-                                  Readme\r
-\r
-                                              Copyright(c) 2010 olyutorskii\r
-\r
-\r
-=== TogaGemとは ===\r
-\r
-TogaGemは、3D動画制作ツール、MikuMikuDance(MMD)で用いられる\r
-各種データファイルを読み書きするためのJavaライブラリです。\r
-TogaGemは、MikuTogaプロジェクトの派生ライブラリとして、\r
-TogaParserライブラリの1.103.2版を引き継ぐ形で誕生しました。\r
-\r
-MikuTogaプロジェクトは、MMDによる3Dアニメーション制作を支援するプログラムの\r
-整備のために発足した、オープンソースプロジェクトです。\r
-\r
-現時点では、PMDモデルファイル(*.pmd)の読み書きが可能です。\r
-\r
-※ MMD開発者の樋口M氏は、MikuTogaの開発活動に一切関与していません。\r
-  TogaGemに関する問い合わせをを樋口M氏へ投げかけないように!約束だよ!\r
-\r
-\r
-=== 実行環境 ===\r
-\r
- - TogaGemはJava言語(JLS3)で記述されたプログラムです。\r
- - TogaGemはJRE1.6に準拠したJava実行環境で利用できるように作られています。\r
-   原則として、JRE1.6に準拠した実行系であれば、プラットフォームを選びません。\r
-\r
-\r
-=== アーカイブ管理体制 ===\r
-\r
-  このアーカイブは、UTF-8による開発環境を前提として構成されています。\r
-  このアーカイブの原本となる開発資産は、\r
-      http://hg.sourceforge.jp/view/mikutoga/TogaGem\r
-  を上位に持つMercurialリポジトリで管理されています。\r
-  アーカイブの代わりにMercurialを通じての開発資産へのアクセスが可能です。\r
-  # hg clone http://hg.sourceforge.jp/view/mikutoga/TogaGem\r
-\r
-\r
-=== 開発プロジェクト運営元 ===\r
-\r
-  http://sourceforge.jp/projects/mikutoga/ まで。\r
-\r
-\r
-=== ディレクトリ内訳構成 ===\r
-\r
-基本的にはMaven2のmaven-archetype-quickstart構成に準じます。\r
-\r
-./README.txt\r
-    あなたが今見てるこれ。\r
-\r
-./CHANGELOG.txt\r
-    変更履歴。\r
-\r
-./LICENSE.txt\r
-    ライセンスに関して。\r
-\r
-./pom.xml\r
-    Maven2用プロジェクト構成定義ファイル。\r
-\r
-./src/main/java/\r
-    Javaのソースコード。\r
-\r
-./src/test/java/\r
-    JUnit 4.* 用のユニットテストコード。\r
-\r
-./src/test/java/sample/\r
-    パーサ利用のサンプルプログラム。\r
-\r
-./src/main/config/\r
-    各種ビルド・構成管理に必要なファイル群。\r
-\r
-./src/main/config/checks.xml\r
-    Checkstyle用configファイル。\r
-\r
-./src/main/config/pmdrules.xml\r
-    PMD用ルール定義ファイル。\r
-\r
-\r
-=== 謝辞 ===\r
-\r
-このライブラリを制作するにあたって、以下の情報を参考にしました。\r
-\r
-\r
-通りすがりの記憶 (T.Tetosuki氏ブログ)\r
-「MMD のモデルデータ(PMD)形式 めも (まとめ)」\r
-http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4\r
-\r
-\r
-PMDエディタver0.0.6.3(極北P氏制作)\r
-同梱readme.txt\r
-\r
-\r
---- EOF ---\r
+[UTF-8 Japanese]
+
+                              T o g a G e m
+                                  Readme
+
+                                              Copyright(c) 2010 olyutorskii
+
+
+=== TogaGemとは ===
+
+TogaGemは、3D動画制作ツール、MikuMikuDance(MMD)で用いられる
+各種データファイルを読み書きするためのJavaライブラリです。
+TogaGemは、MikuTogaプロジェクトの派生ライブラリとして、
+TogaParserライブラリの1.103.2版を引き継ぐ形で誕生しました。
+
+MikuTogaプロジェクトは、MMDによる3Dアニメーション制作を支援するプログラムの
+整備のために発足した、オープンソースプロジェクトです。
+
+現時点では、PMDモデルファイル(*.pmd)の読み書きが可能です。
+
+※ MMD開発者の樋口M氏は、MikuTogaの開発活動に一切関与していません。
+  TogaGemに関する問い合わせをを樋口M氏へ投げかけないように!約束だよ!
+
+
+=== 実行環境 ===
+
+ - TogaGemはJava言語(JLS3)で記述されたプログラムです。
+ - TogaGemはJRE1.6に準拠したJava実行環境で利用できるように作られています。
+   原則として、JRE1.6に準拠した実行系であれば、プラットフォームを選びません。
+
+
+=== アーカイブ管理体制 ===
+
+  このアーカイブは、UTF-8による開発環境を前提として構成されています。
+  このアーカイブの原本となる開発資産は、
+      http://hg.sourceforge.jp/view/mikutoga/TogaGem
+  を上位に持つMercurialリポジトリで管理されています。
+  アーカイブの代わりにMercurialを通じての開発資産へのアクセスが可能です。
+  # hg clone http://hg.sourceforge.jp/view/mikutoga/TogaGem
+
+
+=== 開発プロジェクト運営元 ===
+
+  http://sourceforge.jp/projects/mikutoga/ まで。
+
+
+=== ディレクトリ内訳構成 ===
+
+基本的にはMaven2のmaven-archetype-quickstart構成に準じます。
+
+./README.txt
+    あなたが今見てるこれ。
+
+./CHANGELOG.txt
+    変更履歴。
+
+./LICENSE.txt
+    ライセンスに関して。
+
+./pom.xml
+    Maven2用プロジェクト構成定義ファイル。
+
+./src/main/java/
+    Javaのソースコード。
+
+./src/test/java/
+    JUnit 4.* 用のユニットテストコード。
+
+./src/test/java/sample/
+    パーサ利用のサンプルプログラム。
+
+./src/main/config/
+    各種ビルド・構成管理に必要なファイル群。
+
+./src/main/config/checks.xml
+    Checkstyle用configファイル。
+
+./src/main/config/pmdrules.xml
+    PMD用ルール定義ファイル。
+
+
+=== 謝辞 ===
+
+このライブラリを制作するにあたって、以下の情報を参考にしました。
+
+
+通りすがりの記憶 (T.Tetosuki氏ブログ)
+「MMD のモデルデータ(PMD)形式 めも (まとめ)」
+http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
+
+
+PMDエディタver0.0.6.3(極北P氏制作)
+同梱readme.txt
+
+
+--- EOF ---
index 67da074..0b45e05 100644 (file)
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!DOCTYPE module PUBLIC
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!DOCTYPE module PUBLIC
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+    "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
 
 <!--
     Checkstyle用チェック項目定義。
 
 
 <!--
     Checkstyle用チェック項目定義。
 
-    Checkstyle5.1以降向けに記述。
+    Checkstyle 5.0 以降向けに記述。
 
     [ http://checkstyle.sourceforge.net/ ]
 
 
     [ http://checkstyle.sourceforge.net/ ]
 
 <module name="Checker">
 
     <property name="charset" value="UTF-8" />
 <module name="Checker">
 
     <property name="charset" value="UTF-8" />
+    <property name="localeCountry" value="JP" />
+    <property name="localeLanguage" value="ja" />
     <property name="severity" value="error" />
 
 
     <property name="severity" value="error" />
 
 
+    <!-- Filters -->
+    <module name="SeverityMatchFilter" />
+    <module name="SuppressionFilter">
+        <property name="file" value="src/main/config/suppressions.xml" />
+    </module>
+    <module name="SuppressionCommentFilter" />
+    <module name="SuppressWithNearbyCommentFilter" />
+
+
     <!-- Duplicate Code -->
     <module name="StrictDuplicateCode">
         <property name="min" value="20" />
     <!-- Duplicate Code -->
     <module name="StrictDuplicateCode">
         <property name="min" value="20" />
     <module name="FileTabCharacter" />
 
 
     <module name="FileTabCharacter" />
 
 
-<!-- Filters
-    <module name="SeverityMatchFilter" />
-    <module name="SuppressionFilter" />
-    <module name="SuppressionCommentFilter" />
-    <module name="SuppressWithNearbyCommentFilter" />
--->
-
-
     <module name="TreeWalker">
 
     <module name="TreeWalker">
 
-        <property name="tabWidth" value="4" />
+        <module name="FileContentsHolder" />
 
 
     <!-- Annotations -->
 
 
     <!-- Annotations -->
 <!--    <module name="DesignForExtension" />  -->
         <module name="MutableException" />
         <module name="ThrowsCount">
 <!--    <module name="DesignForExtension" />  -->
         <module name="MutableException" />
         <module name="ThrowsCount">
-            <property name="max" value="4" />
+            <property name="max" value="3" />
         </module>
 
 
         </module>
 
 
             <property name="ignoreSetter" value="true" />
             <property name="ignoreAbstractMethods" value="true" />
         </module>
             <property name="ignoreSetter" value="true" />
             <property name="ignoreAbstractMethods" value="true" />
         </module>
-        <module name="IllegalInstantiation">
-            <property
-                name="classes"
-                value="java.lang.Boolean, java.lang.Integer" />
-        </module>
+        <module name="IllegalInstantiation" />
         <module name="IllegalToken">
             <property name="tokens" value="LITERAL_NATIVE, STATIC_IMPORT" />
         </module>
         <module name="IllegalToken">
             <property name="tokens" value="LITERAL_NATIVE, STATIC_IMPORT" />
         </module>
         <module name="PackageDeclaration" />
         <module name="JUnitTestCase" />
         <module name="ReturnCount">
         <module name="PackageDeclaration" />
         <module name="JUnitTestCase" />
         <module name="ReturnCount">
-            <property name="max" value="3" />
+            <property name="max" value="5" />
         </module>
         <module name="IllegalType" />
         <module name="DeclarationOrder" />
         </module>
         <module name="IllegalType" />
         <module name="DeclarationOrder" />
         <module name="DefaultComesLast" />
         <module name="MissingCtor" />
         <module name="FallThrough" />
         <module name="DefaultComesLast" />
         <module name="MissingCtor" />
         <module name="FallThrough" />
-        <module name="MultipleStringLiterals" />
+        <module name="MultipleStringLiterals">
+            <property
+                name="ignoreStringsRegexp"
+                value="^&quot;&quot;$|^&quot;.&quot;$"
+            />
+        </module>
         <module name="MultipleVariableDeclarations" />
         <module name="UnnecessaryParentheses" />
 
         <module name="MultipleVariableDeclarations" />
         <module name="UnnecessaryParentheses" />
 
         <module name="UpperEll" />
         <module name="ArrayTypeStyle" />
 <!--    <module name="FinalParameters" />  -->
         <module name="UpperEll" />
         <module name="ArrayTypeStyle" />
 <!--    <module name="FinalParameters" />  -->
-        <module name="DescendantToken" />
+<!--    <module name="DescendantToken" />  -->
 <!--
         <module name="Indentation">
 <!--
         <module name="Indentation">
-            <property name="basicOffset" value="4" />
             <property name="caseIndent" value="0" />
         </module>
 -->
             <property name="caseIndent" value="0" />
         </module>
 -->
             <property name="duplicateLimit" value="1" />
         </module>
 
             <property name="duplicateLimit" value="1" />
         </module>
 
+
     <!-- Modifiers -->
 
         <module name="ModifierOrder" />
     <!-- Modifiers -->
 
         <module name="ModifierOrder" />
 
     <!-- Naming Conventions -->
 
 
     <!-- Naming Conventions -->
 
-        <module name="AbstractClassName" />
+        <module name="AbstractClassName">
+            <property
+                name="format"
+                value="^Abstract.*$|^.*Factory$|^.*Builder$|^.*Adapter$"
+            />
+        </module>
         <module name="ClassTypeParameterName" />
         <module name="ConstantName" />
         <module name="LocalFinalVariableName">
         <module name="ClassTypeParameterName" />
         <module name="ConstantName" />
         <module name="LocalFinalVariableName">
         <module name="ParameterName">
             <property name="format" value="^[a-z][_a-zA-Z0-9]*$" />
         </module>
         <module name="ParameterName">
             <property name="format" value="^[a-z][_a-zA-Z0-9]*$" />
         </module>
-        <module name="StaticVariableName">
-            <property name="format" value="^[a-z][_a-zA-Z0-9]*$" />
-        </module>
+        <module name="StaticVariableName" />
         <module name="TypeName" />
 
 
         <module name="TypeName" />
 
 
         <module name="EmptyForInitializerPad" />
         <module name="EmptyForIteratorPad" />
         <module name="MethodParamPad">
         <module name="EmptyForInitializerPad" />
         <module name="EmptyForIteratorPad" />
         <module name="MethodParamPad">
-            <property name="tokens" value="CTOR_DEF, LITERAL_NEW, METHOD_DEF, SUPER_CTOR_CALL" />
+            <property
+                name="tokens"
+                value="CTOR_DEF, LITERAL_NEW, METHOD_DEF, SUPER_CTOR_CALL"
+            />
         </module>
         <module name="NoWhitespaceAfter">
             <property name="allowLineBreaks" value="false" />
         </module>
         <module name="NoWhitespaceAfter">
             <property name="allowLineBreaks" value="false" />
         </module>
         <module name="ParenPad">
             <property name="option" value="nospace" />
         </module>
         <module name="ParenPad">
             <property name="option" value="nospace" />
-            <property name="tokens" value="CTOR_CALL, METHOD_CALL, SUPER_CTOR_CALL" />
+            <property
+                name="tokens"
+                value="CTOR_CALL, METHOD_CALL, SUPER_CTOR_CALL"
+            />
         </module>
         <module name="TypecastParenPad" />
         <module name="WhitespaceAfter">
         </module>
         <module name="TypecastParenPad" />
         <module name="WhitespaceAfter">
                        SL, SR,
                        SL_ASSIGN, SR_ASSIGN,
                        MINUS, STAR, DIV, MOD,
                        SL, SR,
                        SL_ASSIGN, SR_ASSIGN,
                        MINUS, STAR, DIV, MOD,
-                       PLUS_ASSIGN, MINUS_ASSIGN, STAR_ASSIGN, DIV_ASSIGN, MOD_ASSIGN,
+                       PLUS_ASSIGN, MINUS_ASSIGN,
+                       STAR_ASSIGN, DIV_ASSIGN, MOD_ASSIGN,
                        EQUAL, NOT_EQUAL, GT, GE, LT, LE,
                        "
             />
                        EQUAL, NOT_EQUAL, GT, GE, LT, LE,
                        "
             />
 <!-- バグ?
         <module name="RequireThis" />
 -->
 <!-- バグ?
         <module name="RequireThis" />
 -->
+<!-- 5.2 or later
+        <module name="InnerTypeLast" />
+-->
+
+<!-- 5.3 or later
+        <module name="NestedForDepth" />
+        <module name="OneStatementPerLine" />
+        <module name="OuterTypeFilename" />
+        <module name="MethodCount" />
+-->
 
 <!-- Obsolated
         <module name="TabCharacter" />
 -->
 
     </module>
 
 <!-- Obsolated
         <module name="TabCharacter" />
 -->
 
     </module>
+
 </module>
 
 <!-- EOF -->
 </module>
 
 <!-- EOF -->
index 1b5fcf2..ad3dba9 100644 (file)
@@ -9,12 +9,12 @@
 -->
 
 <ruleset
 -->
 
 <ruleset
-  name="Custom ruleset"
   xmlns="http://pmd.sf.net/ruleset/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
   http://pmd.sf.net/ruleset_xml_schema.xsd"
   xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
   xmlns="http://pmd.sf.net/ruleset/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
   http://pmd.sf.net/ruleset_xml_schema.xsd"
   xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
+  name="Custom ruleset"
 >
 
     <rule ref="rulesets/basic.xml">
 >
 
     <rule ref="rulesets/basic.xml">
     <rule ref="rulesets/codesize.xml">
         <exclude name="TooManyMethods" />
     </rule>
     <rule ref="rulesets/codesize.xml">
         <exclude name="TooManyMethods" />
     </rule>
+    <rule ref="rulesets/codesize.xml/TooManyMethods">
+        <properties>
+            <property name="maxmethods" value="25"/>
+        </properties>
+    </rule>
 
     <rule ref="rulesets/clone.xml" />
 
     <rule ref="rulesets/controversial.xml">
 
     <rule ref="rulesets/clone.xml" />
 
     <rule ref="rulesets/controversial.xml">
-        <exclude name="DataflowAnomalyAnalysis" />
+        <exclude name="NullAssignment" />
         <exclude name="OnlyOneReturn" />
         <exclude name="DefaultPackage" />
         <exclude name="OnlyOneReturn" />
         <exclude name="DefaultPackage" />
+        <exclude name="DataflowAnomalyAnalysis" />
     </rule>
 
     <rule ref="rulesets/coupling.xml" />
 
     <rule ref="rulesets/design.xml">
     </rule>
 
     <rule ref="rulesets/coupling.xml" />
 
     <rule ref="rulesets/design.xml">
+        <exclude name="ConfusingTernary" />
         <exclude name="UnnecessaryLocalBeforeReturn" />
     </rule>
 
         <exclude name="UnnecessaryLocalBeforeReturn" />
     </rule>
 
     <rule ref="rulesets/migrating_to_15.xml" />
 
     <rule ref="rulesets/naming.xml">
     <rule ref="rulesets/migrating_to_15.xml" />
 
     <rule ref="rulesets/naming.xml">
-        <exclude name="LongVariable" />
         <exclude name="ShortVariable" />
         <exclude name="ShortVariable" />
+        <exclude name="LongVariable" />
+        <exclude name="AvoidFieldNameMatchingMethodName" />
+    </rule>
+    <rule ref="rulesets/naming.xml/LongVariable">
+        <properties>
+            <property name="minimum" value="25"/>
+        </properties>
     </rule>
 
     <rule ref="rulesets/optimizations.xml">
     </rule>
 
     <rule ref="rulesets/optimizations.xml">
diff --git a/src/main/config/suppressions.xml b/src/main/config/suppressions.xml
new file mode 100644 (file)
index 0000000..1d736c1
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<!--
+    Checkstyle用警告抑止設定
+    ※ SuppressionFilter モジュール用
+
+    [ http://checkstyle.sourceforge.net/ ]
+
+    Copyright(c) 2010 olyutorskii
+-->
+
+
+<suppressions>
+
+<!--
+    <suppress files="" checks="ExecutableStatementCount" />
+
+    <suppress files="" checks="ClassDataAbstractionCoupling" />
+    <suppress files="" checks="ClassFanOutComplexity" />
+    <suppress files="" checks="CyclomaticComplexity" />
+    <suppress files="" checks="NPathComplexity" />
+    <suppress files="" checks="JavaNCSS" />
+-->
+
+<!--
+    <suppress files="" checks="MagicNumber" />
+    <suppress files="" checks="MultipleStringLiterals" />
+-->
+
+</suppressions>
+
+
+<!-- EOF -->
index 50e2fb7..001fa45 100644 (file)
-/*\r
- * international text\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.corelib;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Locale;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-/**\r
- * 多言語のバリアントを持つ文字列情報。\r
- * <ul>\r
- * <li>プライマリ:識別子にはこちらを使う。基本は日本語。\r
- * <li>グローバル:基本は英語。UCS Basic-Latinオンリーの貧弱な言語環境でも\r
- * 読める文字列が望ましい。\r
- * <li>その他:必要に応じて好きな言語を。\r
- * </ul>\r
- */\r
-public class I18nText implements CharSequence {\r
-\r
-    /** プライマリ言語のロケール。 */\r
-    public static final Locale LOCALE_PRIMARY = Locale.JAPANESE;\r
-    /** プライマリ言語の言語コード。 */\r
-    public static final String CODE639_PRIMARY = LOCALE_PRIMARY.getLanguage();\r
-\r
-    /** グローバル言語のロケール。 */\r
-    public static final Locale LOCALE_GLOBAL = Locale.ENGLISH;\r
-    /** グローバル言語の言語コード。 */\r
-    public static final String CODE639_GLOBAL = LOCALE_GLOBAL.getLanguage();\r
-\r
-    static{\r
-        assert CODE639_PRIMARY.equals("ja");\r
-        assert CODE639_GLOBAL .equals("en");\r
-    }\r
-\r
-    private final Map<String, String> nameMap = new HashMap<String, String>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public I18nText(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * プライマリ文字列の登録。\r
-     * @param seq プライマリ文字列。nullの場合は削除動作\r
-     */\r
-    public void setPrimaryText(CharSequence seq){\r
-        setText(CODE639_PRIMARY, seq);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * グローバル文字列の登録。\r
-     * @param seq グローバル文字列。nullの場合は削除動作\r
-     */\r
-    public void setGlobalText(CharSequence seq){\r
-        setText(CODE639_GLOBAL, seq);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 任意のロケールに関連付けられた文字列の登録。\r
-     * @param locale ロケール\r
-     * @param seq 文字列。nullの場合は削除動作\r
-     * @throws NullPointerException ロケール引数がnull\r
-     */\r
-    public void setText(Locale locale, CharSequence seq)\r
-            throws NullPointerException{\r
-        String code639 = locale.getLanguage();\r
-        setText(code639, seq);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 任意の言語コードに関連付けられた文字列の登録。\r
-     * @param code639 ISO639言語コード\r
-     * @param seq 文字列。nullの場合は削除動作\r
-     * @throws NullPointerException 言語コードがnull\r
-     */\r
-    public void setText(String code639, CharSequence seq)\r
-            throws NullPointerException{\r
-        if(code639 == null) throw new NullPointerException();\r
-\r
-        if(seq != null){\r
-            String text = seq.toString();\r
-            this.nameMap.put(code639, text);\r
-        }else{\r
-            this.nameMap.remove(code639);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 言語コードに応じた文字列を返す。\r
-     * @param code639 ISO639言語コード\r
-     * @return 文字列。見つからなければnullを返す。\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public String getText(String code639) throws NullPointerException{\r
-        if(code639 == null) throw new NullPointerException();\r
-        String result = this.nameMap.get(code639);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * ロケールに応じた文字列を返す。\r
-     * @param locale ロケール\r
-     * @return 文字列。見つからなければnullを返す。\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public String getText(Locale locale) throws NullPointerException{\r
-        String code639 = locale.getLanguage();\r
-        String result = getText(code639);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * プライマリ文字列を返す。\r
-     * @return 文字列。見つからなければnullを返す。\r
-     */\r
-    public String getPrimaryText(){\r
-        String result = getText(CODE639_PRIMARY);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * グローバル文字列を返す。\r
-     * @return 文字列。見つからなければnullを返す。\r
-     */\r
-    public String getGlobalText(){\r
-        String result = getText(CODE639_GLOBAL);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * プライマリ文字列を返す。\r
-     * 見つからなければグローバル文字列を返す。\r
-     * それでも見つからなければ空文字列を返す。\r
-     * @return 文字列\r
-     */\r
-    public String getText(){\r
-        String result;\r
-\r
-        result = getPrimaryText();\r
-\r
-        if(result == null){\r
-            result = getGlobalText();\r
-        }\r
-\r
-        if(result == null){\r
-            result = "";\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 実行環境のデフォルトロケールに応じた文字列を返す。\r
-     * 見つからなければグローバル文字列、プライマリ文字列の順に返す。\r
-     * それでも見つからなければ適当な言語コードの文字列を返す。\r
-     * それでも見つからなければ空文字列を返す。\r
-     * デフォルトロケールの確認はその都度行われる。\r
-     * @return 文字列\r
-     */\r
-    public String getLocalizedText(){\r
-        Locale locale = Locale.getDefault();\r
-        String langCode = locale.getLanguage();\r
-\r
-        String result;\r
-\r
-        result = this.nameMap.get(langCode);\r
-\r
-        if(result == null){\r
-            result = this.nameMap.get(CODE639_GLOBAL);\r
-        }\r
-\r
-        if(result == null){\r
-            result = this.nameMap.get(CODE639_PRIMARY);\r
-        }\r
-\r
-        if(result == null){\r
-            Set<String> langSet = this.nameMap.keySet();\r
-            Iterator<String> it = langSet.iterator();\r
-            while(it.hasNext()){\r
-                String lang = it.next();\r
-                result = this.nameMap.get(lang);\r
-                if(result != null) break;\r
-            }\r
-        }\r
-\r
-        if(result == null){\r
-            result = "";\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 全言語の文字列を削除する。\r
-     */\r
-    public void removeAllText(){\r
-        this.nameMap.clear();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 登録済みの全ISO639言語コードリストを返す。\r
-     * 優先度はプライマリ、グローバル、その他の順。\r
-     * @return 全ISO639言語コード\r
-     */\r
-    public List<String> lang639CodeList(){\r
-        Set<String> set = this.nameMap.keySet();\r
-        List<String> result = new ArrayList<String>(set.size());\r
-\r
-        for(String lang : set){\r
-            if(lang.equals(CODE639_PRIMARY)) result.add(lang);\r
-        }\r
-\r
-        for(String lang : set){\r
-            if(lang.equals(CODE639_GLOBAL)) result.add(lang);\r
-        }\r
-\r
-        for(String lang : set){\r
-            if(lang.equals(CODE639_PRIMARY)) continue;\r
-            if(lang.equals(CODE639_GLOBAL)) continue;\r
-            result.add(lang);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * プライマリ文字列が登録されているか判定する。\r
-     * @return 登録されていればtrue\r
-     */\r
-    public boolean hasPrimaryText(){\r
-        boolean result = this.nameMap.containsKey(CODE639_PRIMARY);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * グローバル文字列が登録されているか判定する。\r
-     * @return 登録されていればtrue\r
-     */\r
-    public boolean hasGlobalText(){\r
-        boolean result = this.nameMap.containsKey(CODE639_GLOBAL);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * {@link #getText()}に準ずる。\r
-     * @param index {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public char charAt(int index){\r
-        String text = getText();\r
-        char result = text.charAt(index);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * {@link #getText()}に準ずる。\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int length(){\r
-        String text = getText();\r
-        int result = text.length();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * {@link #getText()}に準ずる。\r
-     * @param start {@inheritDoc}\r
-     * @param end {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public CharSequence subSequence(int start, int end){\r
-        String text = getText();\r
-        CharSequence result = text.subSequence(start, end);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * {@link #getText()}に準ずる。\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        return getText();\r
-    }\r
-\r
-}\r
+/*
+ * international text
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.corelib;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 多言語のバリアントを持つ文字列情報。
+ * <ul>
+ * <li>プライマリ:識別子にはこちらを使う。基本は日本語。
+ * <li>グローバル:基本は英語。UCS Basic-Latinオンリーの貧弱な言語環境でも
+ * 読める文字列が望ましい。
+ * <li>その他:必要に応じて好きな言語を。
+ * </ul>
+ */
+public class I18nText implements CharSequence {
+
+    /** プライマリ言語のロケール。 */
+    public static final Locale LOCALE_PRIMARY = Locale.JAPANESE;
+    /** プライマリ言語の言語コード。 */
+    public static final String CODE639_PRIMARY = LOCALE_PRIMARY.getLanguage();
+
+    /** グローバル言語のロケール。 */
+    public static final Locale LOCALE_GLOBAL = Locale.ENGLISH;
+    /** グローバル言語の言語コード。 */
+    public static final String CODE639_GLOBAL = LOCALE_GLOBAL.getLanguage();
+
+    static{
+        assert CODE639_PRIMARY.equals("ja");
+        assert CODE639_GLOBAL .equals("en");
+    }
+
+    private final Map<String, String> nameMap = new HashMap<String, String>();
+
+    /**
+     * コンストラクタ。
+     */
+    public I18nText(){
+        super();
+        return;
+    }
+
+    /**
+     * プライマリ文字列の登録。
+     * @param seq プライマリ文字列。nullの場合は削除動作
+     */
+    public void setPrimaryText(CharSequence seq){
+        setText(CODE639_PRIMARY, seq);
+        return;
+    }
+
+    /**
+     * グローバル文字列の登録。
+     * @param seq グローバル文字列。nullの場合は削除動作
+     */
+    public void setGlobalText(CharSequence seq){
+        setText(CODE639_GLOBAL, seq);
+        return;
+    }
+
+    /**
+     * 任意のロケールに関連付けられた文字列の登録。
+     * @param locale ロケール
+     * @param seq 文字列。nullの場合は削除動作
+     * @throws NullPointerException ロケール引数がnull
+     */
+    public void setText(Locale locale, CharSequence seq)
+            throws NullPointerException{
+        String code639 = locale.getLanguage();
+        setText(code639, seq);
+        return;
+    }
+
+    /**
+     * 任意の言語コードに関連付けられた文字列の登録。
+     * @param code639 ISO639言語コード
+     * @param seq 文字列。nullの場合は削除動作
+     * @throws NullPointerException 言語コードがnull
+     */
+    public void setText(String code639, CharSequence seq)
+            throws NullPointerException{
+        if(code639 == null) throw new NullPointerException();
+
+        if(seq != null){
+            String text = seq.toString();
+            this.nameMap.put(code639, text);
+        }else{
+            this.nameMap.remove(code639);
+        }
+
+        return;
+    }
+
+    /**
+     * 言語コードに応じた文字列を返す。
+     * @param code639 ISO639言語コード
+     * @return 文字列。見つからなければnullを返す。
+     * @throws NullPointerException 引数がnull
+     */
+    public String getText(String code639) throws NullPointerException{
+        if(code639 == null) throw new NullPointerException();
+        String result = this.nameMap.get(code639);
+        return result;
+    }
+
+    /**
+     * ロケールに応じた文字列を返す。
+     * @param locale ロケール
+     * @return 文字列。見つからなければnullを返す。
+     * @throws NullPointerException 引数がnull
+     */
+    public String getText(Locale locale) throws NullPointerException{
+        String code639 = locale.getLanguage();
+        String result = getText(code639);
+        return result;
+    }
+
+    /**
+     * プライマリ文字列を返す。
+     * @return 文字列。見つからなければnullを返す。
+     */
+    public String getPrimaryText(){
+        String result = getText(CODE639_PRIMARY);
+        return result;
+    }
+
+    /**
+     * グローバル文字列を返す。
+     * @return 文字列。見つからなければnullを返す。
+     */
+    public String getGlobalText(){
+        String result = getText(CODE639_GLOBAL);
+        return result;
+    }
+
+    /**
+     * プライマリ文字列を返す。
+     * 見つからなければグローバル文字列を返す。
+     * それでも見つからなければ空文字列を返す。
+     * @return 文字列
+     */
+    public String getText(){
+        String result;
+
+        result = getPrimaryText();
+
+        if(result == null){
+            result = getGlobalText();
+        }
+
+        if(result == null){
+            result = "";
+        }
+
+        return result;
+    }
+
+    /**
+     * 実行環境のデフォルトロケールに応じた文字列を返す。
+     * 見つからなければグローバル文字列、プライマリ文字列の順に返す。
+     * それでも見つからなければ適当な言語コードの文字列を返す。
+     * それでも見つからなければ空文字列を返す。
+     * デフォルトロケールの確認はその都度行われる。
+     * @return 文字列
+     */
+    public String getLocalizedText(){
+        Locale locale = Locale.getDefault();
+        String langCode = locale.getLanguage();
+
+        String result;
+
+        result = this.nameMap.get(langCode);
+
+        if(result == null){
+            result = this.nameMap.get(CODE639_GLOBAL);
+        }
+
+        if(result == null){
+            result = this.nameMap.get(CODE639_PRIMARY);
+        }
+
+        if(result == null){
+            Set<String> langSet = this.nameMap.keySet();
+            Iterator<String> it = langSet.iterator();
+            while(it.hasNext()){
+                String lang = it.next();
+                result = this.nameMap.get(lang);
+                if(result != null) break;
+            }
+        }
+
+        if(result == null){
+            result = "";
+        }
+
+        return result;
+    }
+
+    /**
+     * 全言語の文字列を削除する。
+     */
+    public void removeAllText(){
+        this.nameMap.clear();
+        return;
+    }
+
+    /**
+     * 登録済みの全ISO639言語コードリストを返す。
+     * 優先度はプライマリ、グローバル、その他の順。
+     * @return 全ISO639言語コード
+     */
+    public List<String> lang639CodeList(){
+        Set<String> set = this.nameMap.keySet();
+        List<String> result = new ArrayList<String>(set.size());
+
+        for(String lang : set){
+            if(lang.equals(CODE639_PRIMARY)) result.add(lang);
+        }
+
+        for(String lang : set){
+            if(lang.equals(CODE639_GLOBAL)) result.add(lang);
+        }
+
+        for(String lang : set){
+            if(lang.equals(CODE639_PRIMARY)) continue;
+            if(lang.equals(CODE639_GLOBAL)) continue;
+            result.add(lang);
+        }
+
+        return result;
+    }
+
+    /**
+     * プライマリ文字列が登録されているか判定する。
+     * @return 登録されていればtrue
+     */
+    public boolean hasPrimaryText(){
+        boolean result = this.nameMap.containsKey(CODE639_PRIMARY);
+        return result;
+    }
+
+    /**
+     * グローバル文字列が登録されているか判定する。
+     * @return 登録されていればtrue
+     */
+    public boolean hasGlobalText(){
+        boolean result = this.nameMap.containsKey(CODE639_GLOBAL);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * {@link #getText()}に準ずる。
+     * @param index {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public char charAt(int index){
+        String text = getText();
+        char result = text.charAt(index);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * {@link #getText()}に準ずる。
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int length(){
+        String text = getText();
+        int result = text.length();
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * {@link #getText()}に準ずる。
+     * @param start {@inheritDoc}
+     * @param end {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public CharSequence subSequence(int start, int end){
+        String text = getText();
+        CharSequence result = text.subSequence(start, end);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * {@link #getText()}に準ずる。
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        return getText();
+    }
+
+}
index af9e099..1093bde 100644 (file)
-/*\r
- * List utilities\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.corelib;\r
-\r
-import java.lang.reflect.Constructor;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.util.Collection;\r
-import java.util.List;\r
-\r
-/**\r
- * リスト構造の各種ユーティリティ。\r
- */\r
-public final class ListUtil {\r
-\r
-    /**\r
-     * 隠しコンストラクタ。\r
-     */\r
-    private ListUtil(){\r
-        assert false;\r
-        throw new AssertionError();\r
-    }\r
-\r
-    /**\r
-     * リストの出現順にシリアルナンバーを割り振る。\r
-     * シリアルナンバー先頭は0。\r
-     * @param list リスト。なるべく{@link java.util.RandomAccess}型が望ましい。\r
-     */\r
-    public static void assignIndexedSerial(\r
-            List<? extends SerialNumbered> list){\r
-        int size = list.size();\r
-        for(int idx = 0; idx < size; idx++){\r
-            SerialNumbered numbered = list.get(idx);\r
-            numbered.setSerialNumber(idx);\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コレクションの要素数を拡張する。\r
-     * 追加された要素にはnullが収められる。\r
-     * コレクションがすでに指定サイズ以上の要素数を持つ場合、何もしない。\r
-     * @param <E> 型\r
-     * @param coll コレクション\r
-     * @param newSize 新サイズ\r
-     */\r
-    public static <E> void extendCollection(Collection<E> coll, int newSize){\r
-        int remain = newSize - coll.size();\r
-        if(remain <= 0) return;\r
-\r
-        for(int ct = 1; ct <= remain; ct++){\r
-            coll.add(null);\r
-        }\r
-\r
-        assert coll.size() == newSize;\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * リストのnull要素をデフォルトコンストラクタによるインスタンスで埋める。\r
-     * null要素がなければなにもしない。\r
-     * @param <E> 型\r
-     * @param list リスト\r
-     * @param cons コンストラクタ\r
-     * @return 埋めた数\r
-     */\r
-    public static <E> int fillDefCons(List<E> list,\r
-                                      Constructor<? extends E> cons){\r
-        int result = 0;\r
-\r
-        int size = list.size();\r
-        for(int pt = 0; pt < size; pt++){\r
-            E elem = list.get(pt);\r
-            if(elem != null) continue;\r
-\r
-            try{\r
-                elem = cons.newInstance();\r
-            }catch(InstantiationException e){\r
-                assert false;\r
-                throw new AssertionError(e);\r
-            }catch(IllegalAccessException e){\r
-                assert false;\r
-                throw new AssertionError(e);\r
-            }catch(InvocationTargetException e){\r
-                Throwable cause = e.getTargetException();\r
-                if(cause instanceof RuntimeException){\r
-                    throw (RuntimeException) cause;\r
-                }\r
-                if(cause instanceof Error){\r
-                    throw (Error) cause;\r
-                }\r
-                assert false;\r
-                throw new AssertionError(e);\r
-            }\r
-\r
-            list.set(pt, elem);\r
-            result++;\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * リストのnull要素をデフォルトコンストラクタによるインスタンスで埋める。\r
-     * @param <E> 型\r
-     * @param list リスト\r
-     * @param klass デフォルトコンストラクタの属するクラス\r
-     * @return 埋めた数\r
-     */\r
-    public static <E> int fillDefCons(List<E> list, Class<? extends E> klass){\r
-        Constructor<? extends E> cons;\r
-        try{\r
-            cons = klass.getConstructor();\r
-        }catch(NoSuchMethodException e){\r
-            assert false;\r
-            throw new AssertionError(e);\r
-        }\r
-\r
-        return fillDefCons(list, cons);\r
-    }\r
-\r
-    /**\r
-     * リスト要素数の拡張とデフォルトコンストラクタによる要素埋めを行う。\r
-     * 追加された要素および既存のnull要素には\r
-     * デフォルトコンストラクタによるインスタンスが収められる。\r
-     * @param <E> 型\r
-     * @param list リスト\r
-     * @param klass デフォルトコンストラクタの属するクラス\r
-     * @param newSize 新サイズ\r
-     * @return 埋めた数。\r
-     */\r
-    public static <E> int prepareDefConsList(List<E> list,\r
-                                             Class<? extends E> klass,\r
-                                             int newSize ){\r
-        extendCollection(list, newSize);\r
-        int result = fillDefCons(list, klass);\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * List utilities
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.corelib;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * リスト構造の各種ユーティリティ。
+ */
+public final class ListUtil {
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private ListUtil(){
+        assert false;
+        throw new AssertionError();
+    }
+
+    /**
+     * リストの出現順にシリアルナンバーを割り振る。
+     * シリアルナンバー先頭は0。
+     * @param list リスト。なるべく{@link java.util.RandomAccess}型が望ましい。
+     */
+    public static void assignIndexedSerial(
+            List<? extends SerialNumbered> list){
+        int size = list.size();
+        for(int idx = 0; idx < size; idx++){
+            SerialNumbered numbered = list.get(idx);
+            numbered.setSerialNumber(idx);
+        }
+        return;
+    }
+
+    /**
+     * コレクションの要素数を拡張する。
+     * 追加された要素にはnullが収められる。
+     * コレクションがすでに指定サイズ以上の要素数を持つ場合、何もしない。
+     * @param <E> 型
+     * @param coll コレクション
+     * @param newSize 新サイズ
+     */
+    public static <E> void extendCollection(Collection<E> coll, int newSize){
+        int remain = newSize - coll.size();
+        if(remain <= 0) return;
+
+        for(int ct = 1; ct <= remain; ct++){
+            coll.add(null);
+        }
+
+        assert coll.size() == newSize;
+
+        return;
+    }
+
+    /**
+     * リストのnull要素をデフォルトコンストラクタによるインスタンスで埋める。
+     * null要素がなければなにもしない。
+     * @param <E> 型
+     * @param list リスト
+     * @param cons コンストラクタ
+     * @return 埋めた数
+     */
+    public static <E> int fillDefCons(List<E> list,
+                                      Constructor<? extends E> cons){
+        int result = 0;
+
+        int size = list.size();
+        for(int pt = 0; pt < size; pt++){
+            E elem = list.get(pt);
+            if(elem != null) continue;
+
+            try{
+                elem = cons.newInstance();
+            }catch(InstantiationException e){
+                assert false;
+                throw new AssertionError(e);
+            }catch(IllegalAccessException e){
+                assert false;
+                throw new AssertionError(e);
+            }catch(InvocationTargetException e){
+                Throwable cause = e.getTargetException();
+                if(cause instanceof RuntimeException){
+                    throw (RuntimeException) cause;
+                }
+                if(cause instanceof Error){
+                    throw (Error) cause;
+                }
+                assert false;
+                throw new AssertionError(e);
+            }
+
+            list.set(pt, elem);
+            result++;
+        }
+
+        return result;
+    }
+
+    /**
+     * リストのnull要素をデフォルトコンストラクタによるインスタンスで埋める。
+     * @param <E> 型
+     * @param list リスト
+     * @param klass デフォルトコンストラクタの属するクラス
+     * @return 埋めた数
+     */
+    public static <E> int fillDefCons(List<E> list, Class<? extends E> klass){
+        Constructor<? extends E> cons;
+        try{
+            cons = klass.getConstructor();
+        }catch(NoSuchMethodException e){
+            assert false;
+            throw new AssertionError(e);
+        }
+
+        return fillDefCons(list, cons);
+    }
+
+    /**
+     * リスト要素数の拡張とデフォルトコンストラクタによる要素埋めを行う。
+     * 追加された要素および既存のnull要素には
+     * デフォルトコンストラクタによるインスタンスが収められる。
+     * @param <E> 型
+     * @param list リスト
+     * @param klass デフォルトコンストラクタの属するクラス
+     * @param newSize 新サイズ
+     * @return 埋めた数。
+     */
+    public static <E> int prepareDefConsList(List<E> list,
+                                             Class<? extends E> klass,
+                                             int newSize ){
+        extendCollection(list, newSize);
+        int result = fillDefCons(list, klass);
+        return result;
+    }
+
+}
index 4fb2fc9..b7bbba4 100644 (file)
@@ -1,67 +1,67 @@
-/*\r
- * serial-numbered interface\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.corelib;\r
-\r
-import java.util.Comparator;\r
-\r
-/**\r
- * 通し番号を持つオブジェクトの抽象化インタフェース。\r
- */\r
-public interface SerialNumbered {\r
-\r
-    /** 昇順での比較子。 */\r
-    public Comparator<SerialNumbered> COMPARATOR = new SerialComparator();\r
-\r
-    /**\r
-     * 通し番号を設定する。\r
-     * @param num 通し番号\r
-     */\r
-    void setSerialNumber(int num);\r
-\r
-    /**\r
-     * 通し番号を返す。\r
-     * @return 通し番号\r
-     */\r
-    int getSerialNumber();\r
-\r
-    /**\r
-     * 通し番号による比較子Comparator。\r
-     * 通し番号の昇順を定義づける。\r
-     */\r
-    public static class SerialComparator\r
-            implements Comparator<SerialNumbered> {\r
-\r
-        /**\r
-         * コンストラクタ。\r
-         */\r
-        public SerialComparator(){\r
-            super();\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param o1 {@inheritDoc}\r
-         * @param o2 {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public int compare(SerialNumbered o1, SerialNumbered o2){\r
-            if(o1 == o2) return 0;\r
-            if(o1 == null) return -1;\r
-            if(o2 == null) return +1;\r
-\r
-            int ser1 = o1.getSerialNumber();\r
-            int ser2 = o2.getSerialNumber();\r
-\r
-            return ser1 - ser2;\r
-        }\r
-\r
-    }\r
-\r
-}\r
+/*
+ * serial-numbered interface
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.corelib;
+
+import java.util.Comparator;
+
+/**
+ * 通し番号を持つオブジェクトの抽象化インタフェース。
+ */
+public interface SerialNumbered {
+
+    /** 昇順での比較子。 */
+    public Comparator<SerialNumbered> COMPARATOR = new SerialComparator();
+
+    /**
+     * 通し番号を設定する。
+     * @param num 通し番号
+     */
+    void setSerialNumber(int num);
+
+    /**
+     * 通し番号を返す。
+     * @return 通し番号
+     */
+    int getSerialNumber();
+
+    /**
+     * 通し番号による比較子Comparator。
+     * 通し番号の昇順を定義づける。
+     */
+    public static class SerialComparator
+            implements Comparator<SerialNumbered> {
+
+        /**
+         * コンストラクタ。
+         */
+        public SerialComparator(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param o1 {@inheritDoc}
+         * @param o2 {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public int compare(SerialNumbered o1, SerialNumbered o2){
+            if(o1 == o2) return 0;
+            if(o1 == null) return -1;
+            if(o2 == null) return +1;
+
+            int ser1 = o1.getSerialNumber();
+            int ser2 = o2.getSerialNumber();
+
+            return ser1 - ser2;
+        }
+
+    }
+
+}
index 8de5060..fcde2d2 100644 (file)
@@ -1,55 +1,55 @@
-/*\r
- * Windows File utils\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.corelib;\r
-\r
-/**\r
- * Windowsに特化したFileユーティリティ。\r
- */\r
-public final class WinFile {\r
-\r
-    public static final char SEPARATOR_CHAR = '\\';  // \\r
-    public static final String SEPARATOR =\r
-            Character.toString(SEPARATOR_CHAR);\r
-    public static final String PFX_UNC =\r
-            SEPARATOR + SEPARATOR;                   // \\\r
-\r
-    static{\r
-        assert '\\' == 0x005c;\r
-    }\r
-\r
-    /**\r
-     * 隠しコンストラクタ。\r
-     */\r
-    private WinFile(){\r
-        assert false;\r
-        throw new AssertionError();\r
-    }\r
-\r
-    /**\r
-     * Windowsファイル名の正規化を行う。\r
-     * UNCも考慮される。\r
-     * 相対パスは相対パスのまま。\r
-     * <ul>\r
-     * <li>頭の3回以上連続する\記号は2個の\記号に置き換えられる。\r
-     * <li>末尾の1回以上連続する\記号は削除。\r
-     * ただし頭から連続している場合は削除しない。\r
-     * <li>2回以上連続する\記号は1個の\記号にまとめられる。\r
-     * ただし頭から連続している場合はまとめない。\r
-     * </ul>\r
-     * @param seq 対象ファイル名\r
-     * @return 正規化されたファイル名\r
-     */\r
-    public static String normalizeWinFileName(CharSequence seq){\r
-        String text = seq.toString();\r
-        text = text.replaceAll("^\\\\{3,}", "\\\\\\\\");\r
-        text = text.replaceAll("(.*[^\\\\])\\\\+$", "$1");\r
-        text = text.replaceAll("([^\\\\])\\\\{2,}", "$1\\\\");\r
-        return text;\r
-    }\r
-\r
-}\r
+/*
+ * Windows File utils
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.corelib;
+
+/**
+ * Windowsに特化したFileユーティリティ。
+ */
+public final class WinFile {
+
+    public static final char SEPARATOR_CHAR = '\\';  // \
+    public static final String SEPARATOR =
+            Character.toString(SEPARATOR_CHAR);
+    public static final String PFX_UNC =
+            SEPARATOR + SEPARATOR;                   // \\
+
+    static{
+        assert '\\' == 0x005c;
+    }
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private WinFile(){
+        assert false;
+        throw new AssertionError();
+    }
+
+    /**
+     * Windowsファイル名の正規化を行う。
+     * UNCも考慮される。
+     * 相対パスは相対パスのまま。
+     * <ul>
+     * <li>頭の3回以上連続する\記号は2個の\記号に置き換えられる。
+     * <li>末尾の1回以上連続する\記号は削除。
+     * ただし頭から連続している場合は削除しない。
+     * <li>2回以上連続する\記号は1個の\記号にまとめられる。
+     * ただし頭から連続している場合はまとめない。
+     * </ul>
+     * @param seq 対象ファイル名
+     * @return 正規化されたファイル名
+     */
+    public static String normalizeWinFileName(CharSequence seq){
+        String text = seq.toString();
+        text = text.replaceAll("^\\\\{3,}", "\\\\\\\\");
+        text = text.replaceAll("(.*[^\\\\])\\\\+$", "$1");
+        text = text.replaceAll("([^\\\\])\\\\{2,}", "$1\\\\");
+        return text;
+    }
+
+}
index 5f416f3..14c138f 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * MikuToga共通基盤ライブラリ。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.corelib;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * MikuToga共通基盤ライブラリ。
+ */
+
+package jp.sourceforge.mikutoga.corelib;
+
+/* EOF */
index 443c86a..1dc8934 100644 (file)
-/*\r
- * common MMD parser\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-import java.io.IOException;\r
-import java.nio.ByteBuffer;\r
-import java.nio.CharBuffer;\r
-import java.nio.charset.Charset;\r
-import java.nio.charset.CharsetDecoder;\r
-import java.nio.charset.CoderResult;\r
-import java.nio.charset.CodingErrorAction;\r
-\r
-/**\r
- * 各種パーサの共通実装。\r
- */\r
-public class CommonParser {\r
-\r
-    /** 日本語デコード作業用入力バッファ長。バイト単位。 */\r
-    public static final int TEXTBUF_SZ = 512;\r
-\r
-    /**\r
-     * MMD各種ファイルで用いられる日本語エンコーディング。(windows-31j)\r
-     * ほぼShift_JISのスーパーセットと思ってよい。\r
-     * デコード結果はUCS-2集合に収まるはず。\r
-     */\r
-    protected static final Charset CS_WIN31J = Charset.forName("windows-31j");\r
-\r
-    private static final byte TERMINATOR = (byte) '\0';  // 0x00\r
-    private static final char UCSYEN = '\u00a5';\r
-    private static final char SJISYEN = (char) 0x005c;  // '\u005c\u005c';\r
-\r
-    private final MmdSource source;\r
-    private final CharsetDecoder decoder;\r
-    private final byte[] textArray;\r
-    private final ByteBuffer textBuffer;  // textArrayの別ビュー\r
-    private final CharBuffer charBuffer;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public CommonParser(MmdSource source){\r
-        super();\r
-\r
-        this.source = source;\r
-        this.decoder = CS_WIN31J.newDecoder();\r
-        this.textArray = new byte[TEXTBUF_SZ];\r
-        this.textBuffer = ByteBuffer.wrap(this.textArray);\r
-        int maxChars =\r
-                (int)(TEXTBUF_SZ * (this.decoder.maxCharsPerByte())) + 1;\r
-        this.charBuffer = CharBuffer.allocate(maxChars);\r
-\r
-        this.decoder.onMalformedInput(CodingErrorAction.REPORT);\r
-        this.decoder.onUnmappableCharacter(CodingErrorAction.REPORT);\r
-        this.textBuffer.clear();\r
-        this.charBuffer.clear();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースにまだデータが残っているか判定する。\r
-     * @return まだ読み込んでいないデータが残っていればtrue\r
-     * @throws IOException IOエラー\r
-     * @see MmdSource#hasMore()\r
-     */\r
-    protected boolean hasMore() throws IOException{\r
-        boolean result = this.source.hasMore();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースを読み飛ばす。\r
-     * @param skipLength 読み飛ばすバイト数。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。\r
-     * @see MmdSource#skip(long)\r
-     */\r
-    protected void skip(long skipLength)\r
-            throws IOException, MmdEofException {\r
-        long result = this.source.skip(skipLength);\r
-        if(result != skipLength){\r
-            throw new MmdEofException(this.source.getPosition());\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースを読み飛ばす。\r
-     * @param skipLength 読み飛ばすバイト数。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。\r
-     * @see MmdSource#skip(long)\r
-     */\r
-    protected void skip(int skipLength)\r
-            throws IOException, MmdEofException {\r
-        skip((long) skipLength);\r
-    }\r
-\r
-    /**\r
-     * byte値を読み込む。\r
-     * @return 読み込んだbyte値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseByte()\r
-     */\r
-    protected byte parseByte()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseByte();\r
-    }\r
-\r
-    /**\r
-     * 符号無し値としてbyte値を読み込み、int型に変換して返す。\r
-     * 符号は拡張されない。(0xffは0x000000ffとなる)\r
-     * @return 読み込まれた値のint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseUByteAsInteger()\r
-     */\r
-    protected int parseUByteAsInteger()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseUByteAsInteger();\r
-    }\r
-\r
-    /**\r
-     * byte値を読み込み、boolean型に変換して返す。\r
-     * 0x00は偽、それ以外は真と解釈される。\r
-     * @return 読み込まれた値のboolean値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseBoolean()\r
-     */\r
-    protected boolean parseBoolean()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseBoolean();\r
-    }\r
-\r
-    /**\r
-     * short値を読み込む。\r
-     * short値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだshort値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseShort()\r
-     */\r
-    protected short parseShort()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseShort();\r
-    }\r
-\r
-    /**\r
-     * 符号無し値としてshort値を読み込み、int型に変換して返す。\r
-     * 符号は拡張されない。(0xffffは0x0000ffffとなる)\r
-     * short値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込まれた値のint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseUShortAsInteger()\r
-     */\r
-    protected int parseUShortAsInteger()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseUShortAsInteger();\r
-    }\r
-\r
-    /**\r
-     * int値を読み込む。\r
-     * int値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseInteger()\r
-     */\r
-    protected int parseInteger()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseInteger();\r
-    }\r
-\r
-    /**\r
-     * float値を読み込む。\r
-     * float値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだfloat値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseFloat()\r
-     */\r
-    protected float parseFloat()\r
-            throws IOException, MmdEofException{\r
-        return this.source.parseFloat();\r
-    }\r
-\r
-    /**\r
-     * byte配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @param offset 読み込み開始オフセット\r
-     * @param length 読み込みバイト数\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseByteArray(byte[], int, int)\r
-     */\r
-    protected void parseByteArray(byte[] dst, int offset, int length)\r
-            throws IOException,\r
-                   NullPointerException,\r
-                   IndexOutOfBoundsException,\r
-                   MmdEofException {\r
-        this.source.parseByteArray(dst, offset, length);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte配列を読み込む。\r
-     * 配列要素全ての読み込みが試みられる。\r
-     * @param dst 格納先配列\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseByteArray(byte[])\r
-     */\r
-    protected void parseByteArray(byte[] dst)\r
-            throws IOException, NullPointerException, MmdEofException{\r
-        this.source.parseByteArray(dst);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * float配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @param offset 読み込み開始オフセット\r
-     * @param length 読み込みfloat要素数\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseFloatArray(float[], int, int)\r
-     */\r
-    protected void parseFloatArray(float[] dst, int offset, int length)\r
-            throws IOException,\r
-                   NullPointerException,\r
-                   IndexOutOfBoundsException,\r
-                   MmdEofException {\r
-        this.source.parseFloatArray(dst, offset, length);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * float配列を読み込む。\r
-     * 配列要素全ての読み込みが試みられる。\r
-     * @param dst 格納先配列\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see MmdSource#parseFloatArray(float[])\r
-     */\r
-    protected void parseFloatArray(float[] dst)\r
-            throws IOException, NullPointerException, MmdEofException{\r
-        this.source.parseFloatArray(dst);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定された最大バイト長に収まるゼロ終端(0x00)文字列を読み込む。\r
-     * 入力バイト列はwindows-31jエンコーディングとして解釈される。\r
-     * ゼロ終端以降のデータは無視されるが、\r
-     * IO入力は指定バイト数だけ読み進められる。\r
-     * ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、\r
-     * そこまでのデータから文字列を構成する。\r
-     * <p>\r
-     * 戻り結果にはU+00A5(UCS円通貨記号)が含まれないことが保証される。\r
-     * ※0x5c(Win31J円通貨)はU+005C(UCSバックスラッシュ)にデコードされる。\r
-     *\r
-     * @param maxlen 読み込みバイト数\r
-     * @return デコードされた文字列\r
-     * @throws IOException IOエラー\r
-     * @throws IllegalArgumentException 読み込みバイト数が負であるか、\r
-     * または内部バッファに対し大きすぎる。\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @throws MmdFormatException 不正な文字エンコーディングが検出された。\r
-     */\r
-    protected String parseZeroTermString(int maxlen)\r
-            throws IOException,\r
-                   IllegalArgumentException,\r
-                   MmdEofException,\r
-                   MmdFormatException {\r
-        if(this.textArray.length < maxlen || maxlen < 0){\r
-            throw new IllegalArgumentException();\r
-        }\r
-\r
-        this.source.parseByteArray(this.textArray, 0, maxlen);\r
-\r
-        int length = -1;\r
-        for(int pos = 0; pos < maxlen; pos++){\r
-            byte ch = this.textArray[pos];\r
-            if(ch == TERMINATOR){\r
-                length = pos;\r
-                break;\r
-            }\r
-        }\r
-        if(length < 0) length = maxlen;\r
-\r
-        this.textBuffer.rewind();\r
-        this.textBuffer.limit(length);\r
-        this.charBuffer.clear();\r
-        CoderResult decResult =\r
-                this.decoder.decode(this.textBuffer, this.charBuffer, true);\r
-        if( ! decResult.isUnderflow() || decResult.isError()){\r
-            throw new MmdFormatException("illegal character encoding",\r
-                                         this.source.getPosition() );\r
-        }\r
-\r
-        this.charBuffer.flip();\r
-        String result = this.charBuffer.toString();\r
-\r
-        if(result.indexOf(UCSYEN) >= 0){\r
-            result = result.replace(UCSYEN, SJISYEN);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * common MMD parser
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * 各種パーサの共通実装。
+ */
+public class CommonParser {
+
+    /** 日本語デコード作業用入力バッファ長。バイト単位。 */
+    public static final int TEXTBUF_SZ = 512;
+
+    /**
+     * MMD各種ファイルで用いられる日本語エンコーディング。(windows-31j)
+     * ほぼShift_JISのスーパーセットと思ってよい。
+     * デコード結果はUCS-2集合に収まるはず。
+     */
+    protected static final Charset CS_WIN31J = Charset.forName("windows-31j");
+
+    private static final byte TERMINATOR = (byte) '\0';  // 0x00
+    private static final char UCSYEN = '\u00a5';
+    private static final char SJISYEN = (char) 0x005c;  // '\u005c\u005c';
+
+    private final MmdSource source;
+    private final CharsetDecoder decoder;
+    private final byte[] textArray;
+    private final ByteBuffer textBuffer;  // textArrayの別ビュー
+    private final CharBuffer charBuffer;
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public CommonParser(MmdSource source){
+        super();
+
+        this.source = source;
+        this.decoder = CS_WIN31J.newDecoder();
+        this.textArray = new byte[TEXTBUF_SZ];
+        this.textBuffer = ByteBuffer.wrap(this.textArray);
+        int maxChars =
+                (int)(TEXTBUF_SZ * (this.decoder.maxCharsPerByte())) + 1;
+        this.charBuffer = CharBuffer.allocate(maxChars);
+
+        this.decoder.onMalformedInput(CodingErrorAction.REPORT);
+        this.decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        this.textBuffer.clear();
+        this.charBuffer.clear();
+
+        return;
+    }
+
+    /**
+     * 入力ソースにまだデータが残っているか判定する。
+     * @return まだ読み込んでいないデータが残っていればtrue
+     * @throws IOException IOエラー
+     * @see MmdSource#hasMore()
+     */
+    protected boolean hasMore() throws IOException{
+        boolean result = this.source.hasMore();
+        return result;
+    }
+
+    /**
+     * 入力ソースを読み飛ばす。
+     * @param skipLength 読み飛ばすバイト数。
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
+     * @see MmdSource#skip(long)
+     */
+    protected void skip(long skipLength)
+            throws IOException, MmdEofException {
+        long result = this.source.skip(skipLength);
+        if(result != skipLength){
+            throw new MmdEofException(this.source.getPosition());
+        }
+
+        return;
+    }
+
+    /**
+     * 入力ソースを読み飛ばす。
+     * @param skipLength 読み飛ばすバイト数。
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
+     * @see MmdSource#skip(long)
+     */
+    protected void skip(int skipLength)
+            throws IOException, MmdEofException {
+        skip((long) skipLength);
+    }
+
+    /**
+     * byte値を読み込む。
+     * @return 読み込んだbyte値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseByte()
+     */
+    protected byte parseByte()
+            throws IOException, MmdEofException{
+        return this.source.parseByte();
+    }
+
+    /**
+     * 符号無し値としてbyte値を読み込み、int型に変換して返す。
+     * 符号は拡張されない。(0xffは0x000000ffとなる)
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseUByteAsInteger()
+     */
+    protected int parseUByteAsInteger()
+            throws IOException, MmdEofException{
+        return this.source.parseUByteAsInteger();
+    }
+
+    /**
+     * byte値を読み込み、boolean型に変換して返す。
+     * 0x00は偽、それ以外は真と解釈される。
+     * @return 読み込まれた値のboolean値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseBoolean()
+     */
+    protected boolean parseBoolean()
+            throws IOException, MmdEofException{
+        return this.source.parseBoolean();
+    }
+
+    /**
+     * short値を読み込む。
+     * short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだshort値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseShort()
+     */
+    protected short parseShort()
+            throws IOException, MmdEofException{
+        return this.source.parseShort();
+    }
+
+    /**
+     * 符号無し値としてshort値を読み込み、int型に変換して返す。
+     * 符号は拡張されない。(0xffffは0x0000ffffとなる)
+     * short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseUShortAsInteger()
+     */
+    protected int parseUShortAsInteger()
+            throws IOException, MmdEofException{
+        return this.source.parseUShortAsInteger();
+    }
+
+    /**
+     * int値を読み込む。
+     * int値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseInteger()
+     */
+    protected int parseInteger()
+            throws IOException, MmdEofException{
+        return this.source.parseInteger();
+    }
+
+    /**
+     * float値を読み込む。
+     * float値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだfloat値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseFloat()
+     */
+    protected float parseFloat()
+            throws IOException, MmdEofException{
+        return this.source.parseFloat();
+    }
+
+    /**
+     * byte配列を読み込む。
+     * @param dst 格納先配列
+     * @param offset 読み込み開始オフセット
+     * @param length 読み込みバイト数
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseByteArray(byte[], int, int)
+     */
+    protected void parseByteArray(byte[] dst, int offset, int length)
+            throws IOException,
+                   NullPointerException,
+                   IndexOutOfBoundsException,
+                   MmdEofException {
+        this.source.parseByteArray(dst, offset, length);
+        return;
+    }
+
+    /**
+     * byte配列を読み込む。
+     * 配列要素全ての読み込みが試みられる。
+     * @param dst 格納先配列
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseByteArray(byte[])
+     */
+    protected void parseByteArray(byte[] dst)
+            throws IOException, NullPointerException, MmdEofException{
+        this.source.parseByteArray(dst);
+        return;
+    }
+
+    /**
+     * float配列を読み込む。
+     * @param dst 格納先配列
+     * @param offset 読み込み開始オフセット
+     * @param length 読み込みfloat要素数
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseFloatArray(float[], int, int)
+     */
+    protected void parseFloatArray(float[] dst, int offset, int length)
+            throws IOException,
+                   NullPointerException,
+                   IndexOutOfBoundsException,
+                   MmdEofException {
+        this.source.parseFloatArray(dst, offset, length);
+        return;
+    }
+
+    /**
+     * float配列を読み込む。
+     * 配列要素全ての読み込みが試みられる。
+     * @param dst 格納先配列
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see MmdSource#parseFloatArray(float[])
+     */
+    protected void parseFloatArray(float[] dst)
+            throws IOException, NullPointerException, MmdEofException{
+        this.source.parseFloatArray(dst);
+        return;
+    }
+
+    /**
+     * 指定された最大バイト長に収まるゼロ終端(0x00)文字列を読み込む。
+     * 入力バイト列はwindows-31jエンコーディングとして解釈される。
+     * ゼロ終端以降のデータは無視されるが、
+     * IO入力は指定バイト数だけ読み進められる。
+     * ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、
+     * そこまでのデータから文字列を構成する。
+     * <p>
+     * 戻り結果にはU+00A5(UCS円通貨記号)が含まれないことが保証される。
+     * ※0x5c(Win31J円通貨)はU+005C(UCSバックスラッシュ)にデコードされる。
+     *
+     * @param maxlen 読み込みバイト数
+     * @return デコードされた文字列
+     * @throws IOException IOエラー
+     * @throws IllegalArgumentException 読み込みバイト数が負であるか、
+     * または内部バッファに対し大きすぎる。
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @throws MmdFormatException 不正な文字エンコーディングが検出された。
+     */
+    protected String parseZeroTermString(int maxlen)
+            throws IOException,
+                   IllegalArgumentException,
+                   MmdEofException,
+                   MmdFormatException {
+        if(this.textArray.length < maxlen || maxlen < 0){
+            throw new IllegalArgumentException();
+        }
+
+        this.source.parseByteArray(this.textArray, 0, maxlen);
+
+        int length = -1;
+        for(int pos = 0; pos < maxlen; pos++){
+            byte ch = this.textArray[pos];
+            if(ch == TERMINATOR){
+                length = pos;
+                break;
+            }
+        }
+        if(length < 0) length = maxlen;
+
+        this.textBuffer.rewind();
+        this.textBuffer.limit(length);
+        this.charBuffer.clear();
+        CoderResult decResult =
+                this.decoder.decode(this.textBuffer, this.charBuffer, true);
+        if( ! decResult.isUnderflow() || decResult.isError()){
+            throw new MmdFormatException("illegal character encoding",
+                                         this.source.getPosition() );
+        }
+
+        this.charBuffer.flip();
+        String result = this.charBuffer.toString();
+
+        if(result.indexOf(UCSYEN) >= 0){
+            result = result.replace(UCSYEN, SJISYEN);
+        }
+
+        return result;
+    }
+
+}
index 5183ede..f20471a 100644 (file)
@@ -1,44 +1,44 @@
-/*\r
- * loop handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-/**\r
- * ループ構造の通知用ハンドラ。\r
- * ステージ指定により、多重ネストループをもサポートする。\r
- */\r
-public interface LoopHandler {\r
-\r
-    /**\r
-     * ループ構造開始の通知を受け取る。\r
-     * 0回ループの場合も含め一度呼ばれる。\r
-     * @param stage ループ種別\r
-     * @param loops ループ回数。未知の場合は負の値。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void loopStart(ParseStage stage, int loops) throws MmdFormatException;\r
-\r
-    /**\r
-     * ループ構造の1イテレーション終了の通知を受け取る。\r
-     * 1度しか回らないループでも呼ばれる。0回ループでは決して呼ばれない。\r
-     * @param stage ループ種別\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void loopNext(ParseStage stage) throws MmdFormatException;\r
-\r
-    /**\r
-     * ループ構造終了の通知を受け取る。\r
-     * 0回ループの場合も含め一度呼ばれる。\r
-     * @param stage ループ種別\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void loopEnd(ParseStage stage) throws MmdFormatException;\r
-\r
-}\r
+/*
+ * loop handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+/**
+ * ループ構造の通知用ハンドラ。
+ * ステージ指定により、多重ネストループをもサポートする。
+ */
+public interface LoopHandler {
+
+    /**
+     * ループ構造開始の通知を受け取る。
+     * 0回ループの場合も含め一度呼ばれる。
+     * @param stage ループ種別
+     * @param loops ループ回数。未知の場合は負の値。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void loopStart(ParseStage stage, int loops) throws MmdFormatException;
+
+    /**
+     * ループ構造の1イテレーション終了の通知を受け取る。
+     * 1度しか回らないループでも呼ばれる。0回ループでは決して呼ばれない。
+     * @param stage ループ種別
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void loopNext(ParseStage stage) throws MmdFormatException;
+
+    /**
+     * ループ構造終了の通知を受け取る。
+     * 0回ループの場合も含め一度呼ばれる。
+     * @param stage ループ種別
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void loopEnd(ParseStage stage) throws MmdFormatException;
+
+}
index fac9deb..3a37fb2 100644 (file)
@@ -1,54 +1,54 @@
-/*\r
- * unexpected file EOF founded exception\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-/**\r
- * 入力ソースが予期せずに終了した異常系。\r
- */\r
-@SuppressWarnings("serial")\r
-public class MmdEofException extends MmdFormatException {\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public MmdEofException(){\r
-        this(null);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message エラーメッセージ\r
-     */\r
-    public MmdEofException(String message){\r
-        this(message, -1L);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param position 入力ソース先頭からのエラー位置。(バイト単位)\r
-     * 負の値を与えると、エラー位置は無効と解釈される。\r
-     */\r
-    public MmdEofException(long position){\r
-        this(null, position);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message エラーメッセージ\r
-     * @param position 入力ソース先頭からのエラー位置。(バイト単位)\r
-     * 負の値を与えると、エラー位置は無効と解釈される。\r
-     */\r
-    public MmdEofException(String message, long position){\r
-        super(message, position);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * unexpected file EOF founded exception
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+/**
+ * 入力ソースが予期せずに終了した異常系。
+ */
+@SuppressWarnings("serial")
+public class MmdEofException extends MmdFormatException {
+
+    /**
+     * コンストラクタ。
+     */
+    public MmdEofException(){
+        this(null);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message エラーメッセージ
+     */
+    public MmdEofException(String message){
+        this(message, -1L);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param position 入力ソース先頭からのエラー位置。(バイト単位)
+     * 負の値を与えると、エラー位置は無効と解釈される。
+     */
+    public MmdEofException(long position){
+        this(null, position);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message エラーメッセージ
+     * @param position 入力ソース先頭からのエラー位置。(バイト単位)
+     * 負の値を与えると、エラー位置は無効と解釈される。
+     */
+    public MmdEofException(String message, long position){
+        super(message, position);
+        return;
+    }
+
+}
index a56822c..3e98fa1 100644 (file)
-/*\r
- * unexpected file format founded exception\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-/**\r
- * MMD関連ファイルのパース異常系。\r
- * 必要に応じて、パースに失敗した位置を保持する。\r
- */\r
-@SuppressWarnings("serial")\r
-public class MmdFormatException extends Exception {\r
-\r
-    private final long position;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public MmdFormatException(){\r
-        this(null);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message エラーメッセージ\r
-     */\r
-    public MmdFormatException(String message){\r
-        this(message, -1L);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param position 入力ソース先頭から数えたエラー位置。(バイト単位)\r
-     * 負の値を与えると、エラー位置は無効と解釈される。\r
-     */\r
-    public MmdFormatException(long position){\r
-        this(null, position);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message エラーメッセージ\r
-     * @param position 入力ソース先頭から数えたエラー位置。(バイト単位)\r
-     * 負の値を与えると、エラー位置は無効と解釈される。\r
-     */\r
-    public MmdFormatException(String message, long position){\r
-        super(message);\r
-        this.position = position;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * 有効なエラー発生位置を保持している場合、追加出力される。\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String getMessage(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        String msg = super.getMessage();\r
-        if(msg != null) result.append(msg);\r
-\r
-        if(hasPosition()){\r
-            result.append('(')\r
-                  .append("position:")\r
-                  .append(this.position)\r
-                  .append(')');\r
-        }\r
-\r
-        if(result.length() <= 0) return null;\r
-\r
-        return result.toString();\r
-    }\r
-\r
-    /**\r
-     * エラー位置を取得する。\r
-     * @return 入力ソース先頭からのバイト数で表されるエラー位置。\r
-     * 負なら無効なエラー位置。\r
-     */\r
-    public long getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * 有効なエラー位置が設定されているか判定する。\r
-     * @return エラー位置が有効(非負)ならtrue\r
-     */\r
-    public boolean hasPosition(){\r
-        if(this.position < 0L) return false;\r
-        return true;\r
-    }\r
-\r
-}\r
+/*
+ * unexpected file format founded exception
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+/**
+ * MMD関連ファイルのパース異常系。
+ * 必要に応じて、パースに失敗した位置を保持する。
+ */
+@SuppressWarnings("serial")
+public class MmdFormatException extends Exception {
+
+    private final long position;
+
+    /**
+     * コンストラクタ。
+     */
+    public MmdFormatException(){
+        this(null);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message エラーメッセージ
+     */
+    public MmdFormatException(String message){
+        this(message, -1L);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param position 入力ソース先頭から数えたエラー位置。(バイト単位)
+     * 負の値を与えると、エラー位置は無効と解釈される。
+     */
+    public MmdFormatException(long position){
+        this(null, position);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message エラーメッセージ
+     * @param position 入力ソース先頭から数えたエラー位置。(バイト単位)
+     * 負の値を与えると、エラー位置は無効と解釈される。
+     */
+    public MmdFormatException(String message, long position){
+        super(message);
+        this.position = position;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 有効なエラー発生位置を保持している場合、追加出力される。
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String getMessage(){
+        StringBuilder result = new StringBuilder();
+
+        String msg = super.getMessage();
+        if(msg != null) result.append(msg);
+
+        if(hasPosition()){
+            result.append('(')
+                  .append("position:")
+                  .append(this.position)
+                  .append(')');
+        }
+
+        if(result.length() <= 0) return null;
+
+        return result.toString();
+    }
+
+    /**
+     * エラー位置を取得する。
+     * @return 入力ソース先頭からのバイト数で表されるエラー位置。
+     * 負なら無効なエラー位置。
+     */
+    public long getPosition(){
+        return this.position;
+    }
+
+    /**
+     * 有効なエラー位置が設定されているか判定する。
+     * @return エラー位置が有効(非負)ならtrue
+     */
+    public boolean hasPosition(){
+        if(this.position < 0L) return false;
+        return true;
+    }
+
+}
index 4c4b43e..cb44f4d 100644 (file)
-/*\r
- * MMD file input source\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-import java.io.Closeable;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.PushbackInputStream;\r
-import java.nio.ByteBuffer;\r
-import java.nio.ByteOrder;\r
-\r
-/**\r
- * MMD各種ファイルの入力ソース。\r
- * 入力ソース終端の判定が可能。\r
- * パースエラー発生位置(バイト単位)の取得が可能。\r
- * リトルエンディアン形式で格納された各種プリミティブ型値の解決を行う。\r
- */\r
-public class MmdSource implements Closeable {\r
-\r
-    private static final int BYTES_SHORT = Short  .SIZE / Byte.SIZE;\r
-    private static final int BYTES_INT   = Integer.SIZE / Byte.SIZE;\r
-    private static final int BYTES_FLOAT = Float  .SIZE / Byte.SIZE;\r
-    private static final int BUF_SZ = 4;\r
-\r
-    private static final int MASK_8BIT = 0xff;\r
-    private static final int MASK_16BIT = 0xffff;\r
-\r
-    static{\r
-        assert BUF_SZ >= BYTES_SHORT;\r
-        assert BUF_SZ >= BYTES_INT;\r
-        assert BUF_SZ >= BYTES_FLOAT;\r
-    }\r
-\r
-    private final PushbackInputStream istream;\r
-    private final byte[] readArray;       // 読み込みバッファ\r
-    private final ByteBuffer readBuffer;  // 読み込みバッファの別ビュー\r
-    private long position;                // 読み込み位置\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param is 入力ストリーム。\r
-     * I/O効率が考慮されたバッファリングを行うストリームを渡すのが望ましい。\r
-     * @throws NullPointerException ストリーム引数がnull。\r
-     */\r
-    public MmdSource(InputStream is)\r
-            throws NullPointerException {\r
-        super();\r
-\r
-        if(is == null) throw new NullPointerException();\r
-\r
-        // 読み戻しバッファは1byte確保\r
-        this.istream = new PushbackInputStream(is);\r
-\r
-        this.readArray = new byte[BUF_SZ];\r
-        this.readBuffer = ByteBuffer.wrap(this.readArray);\r
-        this.readBuffer.order(ByteOrder.LITTLE_ENDIAN);\r
-        this.readBuffer.clear();\r
-\r
-        this.position = 0L;\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 今までに読み込みに成功したバイト数を返す。\r
-     * @return 読み込みに成功したバイト数。\r
-     */\r
-    public long getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースを読み飛ばす。\r
-     * 入力ソースがディスクファイルに由来する場合、\r
-     * 空読みするより早くなるかも。\r
-     * @param skipLength 読み飛ばすバイト数。\r
-     * @return 実際に読み飛ばしたバイト数。\r
-     * @throws IOException IOエラー\r
-     * @see java.io.InputStream#skip(long)\r
-     */\r
-    public long skip(long skipLength)\r
-            throws IOException{\r
-        if(skipLength <= 0L) return 0L;\r
-\r
-        long remain = skipLength;\r
-        while(remain > 0L){      // BufferedInputStream対策\r
-            long result = this.istream.skip(remain);\r
-            if(result <= 0L) break;\r
-            this.position += result;\r
-            remain -= result;\r
-        }\r
-\r
-        return skipLength - remain;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースにまだデータが残っているか判定する。\r
-     * @return まだ読み込んでいないデータが残っていればtrue\r
-     * @throws IOException IOエラー\r
-     */\r
-    public boolean hasMore() throws IOException{\r
-        int bData = this.istream.read();\r
-        if(bData < 0){\r
-            return false;\r
-        }\r
-\r
-        this.istream.unread(bData);\r
-\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * 入力ソースを閉じる。\r
-     * 読み込み済みバイト数の情報は保持される。\r
-     * @throws IOException IOエラー\r
-     * @see java.io.InputStream#close()\r
-     */\r
-    @Override\r
-    public void close() throws IOException{\r
-        this.istream.close();\r
-        this.readBuffer.clear();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定したバイト数だけ内部バッファに読み込む。\r
-     * @param fillSize 読み込むバイト数\r
-     * @throws IOException IOエラー\r
-     * @throws IndexOutOfBoundsException 引数がバッファサイズと矛盾。\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    protected void fillBuffer(int fillSize)\r
-            throws IOException, IndexOutOfBoundsException, MmdEofException{\r
-        int result = this.istream.read(this.readArray, 0, fillSize);\r
-        if(result >= 0){\r
-            this.position += result;\r
-        }\r
-\r
-        if(result != fillSize){\r
-            throw new MmdEofException(this.position);\r
-        }\r
-\r
-        this.readBuffer.rewind();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値を読み込む。\r
-     * @return 読み込んだbyte値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public byte parseByte() throws IOException, MmdEofException{\r
-        int bData = this.istream.read();\r
-        if(bData < 0){\r
-            throw new MmdEofException(this.position);\r
-        }else{\r
-            this.position++;\r
-        }\r
-\r
-        byte result = (byte) bData;\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 符号無し値としてbyte値を読み込み、int型に変換して返す。\r
-     * 符号は拡張されない。(0xffは0x000000ffとなる)\r
-     * @return 読み込まれた値のint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public int parseUByteAsInteger()\r
-            throws IOException, MmdEofException{\r
-        return ((int) parseByte()) & MASK_8BIT;\r
-    }\r
-\r
-    /**\r
-     * byte値を読み込み、boolean型に変換して返す。\r
-     * 0x00は偽、それ以外は真と解釈される。\r
-     * @return 読み込まれた値のboolean値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public boolean parseBoolean() throws IOException, MmdEofException{\r
-        byte result = parseByte();\r
-        if(result == 0x00) return false;\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * short値を読み込む。\r
-     * short値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだshort値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public short parseShort() throws IOException, MmdEofException{\r
-        fillBuffer(BYTES_SHORT);\r
-        short result = this.readBuffer.getShort();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 符号無し値としてshort値を読み込み、int型に変換して返す。\r
-     * 符号は拡張されない。(0xffffは0x0000ffffとなる)\r
-     * short値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込まれた値のint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public int parseUShortAsInteger()\r
-            throws IOException, MmdEofException{\r
-        return ((int) parseShort()) & MASK_16BIT;\r
-    }\r
-\r
-    /**\r
-     * int値を読み込む。\r
-     * int値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだint値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public int parseInteger() throws IOException, MmdEofException{\r
-        fillBuffer(BYTES_INT);\r
-        int result = this.readBuffer.getInt();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * float値を読み込む。\r
-     * float値はリトルエンディアンで格納されていると仮定される。\r
-     * @return 読み込んだfloat値\r
-     * @throws IOException IOエラー\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public float parseFloat() throws IOException, MmdEofException{\r
-        fillBuffer(BYTES_FLOAT);\r
-        float result = this.readBuffer.getFloat();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * byte配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @param offset 読み込み開始オフセット\r
-     * @param length 読み込みバイト数\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     * @see java.io.InputStream#read(byte[], int, int)\r
-     */\r
-    public void parseByteArray(byte[] dst, int offset, int length)\r
-            throws IOException,\r
-                   NullPointerException,\r
-                   IndexOutOfBoundsException,\r
-                   MmdEofException {\r
-        int result = this.istream.read(dst, offset, length);\r
-        if(result >= 0){\r
-            this.position += result;\r
-        }\r
-\r
-        if(result != length){\r
-            throw new MmdEofException(this.position);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public void parseByteArray(byte[] dst)\r
-            throws IOException, NullPointerException, MmdEofException{\r
-        parseByteArray(dst, 0, dst.length);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * float配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @param offset 読み込み開始オフセット\r
-     * @param length 読み込みfloat要素数\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public void parseFloatArray(float[] dst, int offset, int length)\r
-            throws IOException,\r
-                   NullPointerException,\r
-                   IndexOutOfBoundsException,\r
-                   MmdEofException {\r
-        if(offset < 0 || length < 0 || dst.length - offset < length){\r
-            throw new IndexOutOfBoundsException();\r
-        }\r
-\r
-        for(int idx = 0; idx < length; idx++){\r
-            dst[offset+idx] = parseFloat();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * float配列を読み込む。\r
-     * @param dst 格納先配列\r
-     * @throws IOException IOエラー\r
-     * @throws NullPointerException 配列がnull\r
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。\r
-     */\r
-    public void parseFloatArray(float[] dst)\r
-            throws IOException, NullPointerException, MmdEofException{\r
-        parseFloatArray(dst, 0, dst.length);\r
-        return;\r
-    }\r
-\r
-    // TODO ビッグエンディアン対応が今後必要になる状況はありうるか?\r
-}\r
+/*
+ * MMD file input source
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * MMD各種ファイルの入力ソース。
+ * 入力ソース終端の判定が可能。
+ * パースエラー発生位置(バイト単位)の取得が可能。
+ * リトルエンディアン形式で格納された各種プリミティブ型値の解決を行う。
+ */
+public class MmdSource implements Closeable {
+
+    private static final int BYTES_SHORT = Short  .SIZE / Byte.SIZE;
+    private static final int BYTES_INT   = Integer.SIZE / Byte.SIZE;
+    private static final int BYTES_FLOAT = Float  .SIZE / Byte.SIZE;
+    private static final int BUF_SZ = 4;
+
+    private static final int MASK_8BIT = 0xff;
+    private static final int MASK_16BIT = 0xffff;
+
+    static{
+        assert BUF_SZ >= BYTES_SHORT;
+        assert BUF_SZ >= BYTES_INT;
+        assert BUF_SZ >= BYTES_FLOAT;
+    }
+
+    private final PushbackInputStream istream;
+    private final byte[] readArray;       // 読み込みバッファ
+    private final ByteBuffer readBuffer;  // 読み込みバッファの別ビュー
+    private long position;                // 読み込み位置
+
+    /**
+     * コンストラクタ。
+     * @param is 入力ストリーム。
+     * I/O効率が考慮されたバッファリングを行うストリームを渡すのが望ましい。
+     * @throws NullPointerException ストリーム引数がnull。
+     */
+    public MmdSource(InputStream is)
+            throws NullPointerException {
+        super();
+
+        if(is == null) throw new NullPointerException();
+
+        // 読み戻しバッファは1byte確保
+        this.istream = new PushbackInputStream(is);
+
+        this.readArray = new byte[BUF_SZ];
+        this.readBuffer = ByteBuffer.wrap(this.readArray);
+        this.readBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        this.readBuffer.clear();
+
+        this.position = 0L;
+
+        return;
+    }
+
+    /**
+     * 今までに読み込みに成功したバイト数を返す。
+     * @return 読み込みに成功したバイト数。
+     */
+    public long getPosition(){
+        return this.position;
+    }
+
+    /**
+     * 入力ソースを読み飛ばす。
+     * 入力ソースがディスクファイルに由来する場合、
+     * 空読みするより早くなるかも。
+     * @param skipLength 読み飛ばすバイト数。
+     * @return 実際に読み飛ばしたバイト数。
+     * @throws IOException IOエラー
+     * @see java.io.InputStream#skip(long)
+     */
+    public long skip(long skipLength)
+            throws IOException{
+        if(skipLength <= 0L) return 0L;
+
+        long remain = skipLength;
+        while(remain > 0L){      // BufferedInputStream対策
+            long result = this.istream.skip(remain);
+            if(result <= 0L) break;
+            this.position += result;
+            remain -= result;
+        }
+
+        return skipLength - remain;
+    }
+
+    /**
+     * 入力ソースにまだデータが残っているか判定する。
+     * @return まだ読み込んでいないデータが残っていればtrue
+     * @throws IOException IOエラー
+     */
+    public boolean hasMore() throws IOException{
+        int bData = this.istream.read();
+        if(bData < 0){
+            return false;
+        }
+
+        this.istream.unread(bData);
+
+        return true;
+    }
+
+    /**
+     * 入力ソースを閉じる。
+     * 読み込み済みバイト数の情報は保持される。
+     * @throws IOException IOエラー
+     * @see java.io.InputStream#close()
+     */
+    @Override
+    public void close() throws IOException{
+        this.istream.close();
+        this.readBuffer.clear();
+        return;
+    }
+
+    /**
+     * 指定したバイト数だけ内部バッファに読み込む。
+     * @param fillSize 読み込むバイト数
+     * @throws IOException IOエラー
+     * @throws IndexOutOfBoundsException 引数がバッファサイズと矛盾。
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    protected void fillBuffer(int fillSize)
+            throws IOException, IndexOutOfBoundsException, MmdEofException{
+        int result = this.istream.read(this.readArray, 0, fillSize);
+        if(result >= 0){
+            this.position += result;
+        }
+
+        if(result != fillSize){
+            throw new MmdEofException(this.position);
+        }
+
+        this.readBuffer.rewind();
+
+        return;
+    }
+
+    /**
+     * byte値を読み込む。
+     * @return 読み込んだbyte値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public byte parseByte() throws IOException, MmdEofException{
+        int bData = this.istream.read();
+        if(bData < 0){
+            throw new MmdEofException(this.position);
+        }else{
+            this.position++;
+        }
+
+        byte result = (byte) bData;
+        return result;
+    }
+
+    /**
+     * 符号無し値としてbyte値を読み込み、int型に変換して返す。
+     * 符号は拡張されない。(0xffは0x000000ffとなる)
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public int parseUByteAsInteger()
+            throws IOException, MmdEofException{
+        return ((int) parseByte()) & MASK_8BIT;
+    }
+
+    /**
+     * byte値を読み込み、boolean型に変換して返す。
+     * 0x00は偽、それ以外は真と解釈される。
+     * @return 読み込まれた値のboolean値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public boolean parseBoolean() throws IOException, MmdEofException{
+        byte result = parseByte();
+        if(result == 0x00) return false;
+        return true;
+    }
+
+    /**
+     * short値を読み込む。
+     * short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだshort値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public short parseShort() throws IOException, MmdEofException{
+        fillBuffer(BYTES_SHORT);
+        short result = this.readBuffer.getShort();
+        return result;
+    }
+
+    /**
+     * 符号無し値としてshort値を読み込み、int型に変換して返す。
+     * 符号は拡張されない。(0xffffは0x0000ffffとなる)
+     * short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public int parseUShortAsInteger()
+            throws IOException, MmdEofException{
+        return ((int) parseShort()) & MASK_16BIT;
+    }
+
+    /**
+     * int値を読み込む。
+     * int値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public int parseInteger() throws IOException, MmdEofException{
+        fillBuffer(BYTES_INT);
+        int result = this.readBuffer.getInt();
+        return result;
+    }
+
+    /**
+     * float値を読み込む。
+     * float値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだfloat値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public float parseFloat() throws IOException, MmdEofException{
+        fillBuffer(BYTES_FLOAT);
+        float result = this.readBuffer.getFloat();
+        return result;
+    }
+
+    /**
+     * byte配列を読み込む。
+     * @param dst 格納先配列
+     * @param offset 読み込み開始オフセット
+     * @param length 読み込みバイト数
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see java.io.InputStream#read(byte[], int, int)
+     */
+    public void parseByteArray(byte[] dst, int offset, int length)
+            throws IOException,
+                   NullPointerException,
+                   IndexOutOfBoundsException,
+                   MmdEofException {
+        int result = this.istream.read(dst, offset, length);
+        if(result >= 0){
+            this.position += result;
+        }
+
+        if(result != length){
+            throw new MmdEofException(this.position);
+        }
+
+        return;
+    }
+
+    /**
+     * byte配列を読み込む。
+     * @param dst 格納先配列
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public void parseByteArray(byte[] dst)
+            throws IOException, NullPointerException, MmdEofException{
+        parseByteArray(dst, 0, dst.length);
+        return;
+    }
+
+    /**
+     * float配列を読み込む。
+     * @param dst 格納先配列
+     * @param offset 読み込み開始オフセット
+     * @param length 読み込みfloat要素数
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public void parseFloatArray(float[] dst, int offset, int length)
+            throws IOException,
+                   NullPointerException,
+                   IndexOutOfBoundsException,
+                   MmdEofException {
+        if(offset < 0 || length < 0 || dst.length - offset < length){
+            throw new IndexOutOfBoundsException();
+        }
+
+        for(int idx = 0; idx < length; idx++){
+            dst[offset+idx] = parseFloat();
+        }
+
+        return;
+    }
+
+    /**
+     * float配列を読み込む。
+     * @param dst 格納先配列
+     * @throws IOException IOエラー
+     * @throws NullPointerException 配列がnull
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    public void parseFloatArray(float[] dst)
+            throws IOException, NullPointerException, MmdEofException{
+        parseFloatArray(dst, 0, dst.length);
+        return;
+    }
+
+    // TODO ビッグエンディアン対応が今後必要になる状況はありうるか?
+}
index ea04c7d..859e038 100644 (file)
@@ -1,47 +1,47 @@
-/*\r
- * parse-processing stage\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-/**\r
- * パース処理の進行ステージ種別を表す。\r
- * ループ構造の識別に用いられる。\r
- */\r
-public class ParseStage {\r
-\r
-    private final String name;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * 進行ステージ名は空文字列が指定される。\r
-     */\r
-    public ParseStage(){\r
-        this("");\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param name 進行ステージ名\r
-     */\r
-    public ParseStage(String name){\r
-        super();\r
-        this.name = name;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * 進行ステージ名を返す。\r
-     * @return {@inheritDoc} 進行ステージ名\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        return this.name;\r
-    }\r
-\r
-}\r
+/*
+ * parse-processing stage
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+/**
+ * パース処理の進行ステージ種別を表す。
+ * ループ構造の識別に用いられる。
+ */
+public class ParseStage {
+
+    private final String name;
+
+    /**
+     * コンストラクタ。
+     * 進行ステージ名は空文字列が指定される。
+     */
+    public ParseStage(){
+        this("");
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param name 進行ステージ名
+     */
+    public ParseStage(String name){
+        super();
+        this.name = name;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 進行ステージ名を返す。
+     * @return {@inheritDoc} 進行ステージ名
+     */
+    @Override
+    public String toString(){
+        return this.name;
+    }
+
+}
index e01d5f6..116cf8d 100644 (file)
@@ -1,17 +1,17 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * MMD用各種パーサ共通ライブラリ。\r
- * <p>\r
- * PMDモデルファイルやVMDモーションファイルなどの個別のパーサは\r
- * 別パッケージにより提供される。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * MMD用各種パーサ共通ライブラリ。
+ * <p>
+ * PMDモデルファイルやVMDモーションファイルなどの個別のパーサは
+ * 別パッケージにより提供される。
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+/* EOF */
index dccc41c..96bece8 100644 (file)
@@ -1,54 +1,54 @@
-/*\r
- * PMD basic information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-\r
-/**\r
- * PMDモデル情報ファイルの基本情報の通知用ハンドラ。\r
- */\r
-public interface PmdBasicHandler {\r
-\r
-    /**\r
-     * PMDファイルのパース処理開始の通知を受け取る。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdParseStart()\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * PMDファイルのパース処理終了の通知を受け取る。\r
-     * @param hasMoreData 入力ソースに\r
-     * まだ読み込まれていないデータがあればtrue\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdParseEnd(boolean hasMoreData)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * PMDファイルのヘッダ情報の通知を受け取る。\r
-     * @param ver ヘッダ情報の版数。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdHeaderInfo(float ver)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * PMDファイルのモデル基本情報の通知を受け取る。\r
-     * @param modelName モデル名\r
-     * @param description モデルの説明文。改行CRLFは"\n"に変換される。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdModelInfo(String modelName, String description)\r
-            throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD basic information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+
+/**
+ * PMDモデル情報ファイルの基本情報の通知用ハンドラ。
+ */
+public interface PmdBasicHandler {
+
+    /**
+     * PMDファイルのパース処理開始の通知を受け取る。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdParseStart()
+            throws MmdFormatException;
+
+    /**
+     * PMDファイルのパース処理終了の通知を受け取る。
+     * @param hasMoreData 入力ソースに
+     * まだ読み込まれていないデータがあればtrue
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdParseEnd(boolean hasMoreData)
+            throws MmdFormatException;
+
+    /**
+     * PMDファイルのヘッダ情報の通知を受け取る。
+     * @param ver ヘッダ情報の版数。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdHeaderInfo(float ver)
+            throws MmdFormatException;
+
+    /**
+     * PMDファイルのモデル基本情報の通知を受け取る。
+     * @param modelName モデル名
+     * @param description モデルの説明文。改行CRLFは"\n"に変換される。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdModelInfo(String modelName, String description)
+            throws MmdFormatException;
+
+}
index 5cbdf38..c4954f4 100644 (file)
-/*\r
- * PMD bone information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの各種ボーン情報の通知用ハンドラ。\r
- * ボーン定義の出現順と、0から始まるボーンIDは対応する。\r
- */\r
-public interface PmdBoneHandler extends LoopHandler {\r
-\r
-    /**\r
-     * ボーン情報パースステージ。\r
-     */\r
-    class PmdBoneStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdBoneStage(){ super(); return; }\r
-    }\r
-\r
-    /** ボーン定義抽出ループ。 */\r
-    PmdBoneStage BONE_LIST = new PmdBoneStage();\r
-\r
-    /** IKリスト抽出ループ。 */\r
-    PmdBoneStage IK_LIST = new PmdBoneStage();\r
-\r
-    /** IKチェーンリスト抽出ループ。 */\r
-    PmdBoneStage IKCHAIN_LIST = new PmdBoneStage();\r
-\r
-    /** ボーングループ名抽出ループ。 */\r
-    PmdBoneStage BONEGROUP_LIST = new PmdBoneStage();\r
-\r
-    /** ボーングループ内訳抽出ループ。 */\r
-    PmdBoneStage GROUPEDBONE_LIST = new PmdBoneStage();\r
-\r
-    /**\r
-     * ボーン定義情報の通知を受け取る。\r
-     * {@link #BONE_LIST}ループの構成要素。\r
-     * @param boneName ボーン名\r
-     * @param boneKind ボーン種別。\r
-     * <ul>\r
-     * <li>0:回転\r
-     * <li>1:回転/移動\r
-     * <li>2:IK\r
-     * <li>3:不明\r
-     * <li>4:IK影響下(回転)\r
-     * <li>5:回転影響下\r
-     * <li>6:IK接続先\r
-     * <li>7:非表示\r
-     * <li>8:捩り\r
-     * <li>9:回転連動\r
-     * </ul>\r
-     * ※8,9はMMD4.0から?\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdBoneInfo(String boneName, byte boneKind)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * ボーン間接続情報の通知を受け取る。\r
-     * {@link #BONE_LIST}ループの構成要素。\r
-     * @param parentId 親(前)ボーンID。無い場合は0xffff。\r
-     * @param tailId 子(次)ボーンID。末端の場合は0。\r
-     * 捩りボーンの場合は軸方向のボーンID、\r
-     * 回転連動ボーンの場合は影響元ボーンID\r
-     * @param ikId 影響IKボーンID。未指定の場合は0。\r
-     * ※回転連動では影響度(0-100)、負や100以上もOK!\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdBoneLink(int parentId, int tailId, int ikId)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * ボーン位置情報の通知を受け取る。\r
-     * {@link #BONE_LIST}ループの構成要素。\r
-     * @param xPos X座標\r
-     * @param yPos Y座標\r
-     * @param zPos Z座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdBonePosition(float xPos, float yPos, float zPos)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * IKボーン情報の通知を受け取る。\r
-     * {@link #IK_LIST}ループの構成要素。\r
-     * @param boneId IKボーンID\r
-     * @param targetId IKボーンが最初に接続するIK接続先ボーンID\r
-     * @param depth 再帰演算の深さ\r
-     * @param weight 制限角度強度\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdIKInfo(int boneId, int targetId, int depth, float weight)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * IKチェイン要素の通知を受け取る。\r
-     * {@link #IK_LIST}ループの下位{@link #IKCHAIN_LIST}ループの構成要素。\r
-     * @param childId IK影響下ボーンID\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdIKChainInfo(int childId)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * ボーングループ名定義の通知を受け取る。\r
-     * {@link #BONEGROUP_LIST}ループの構成要素。\r
-     * @param groupName ボーングループ名。末尾のLF(0x0a)は削除される。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdBoneGroupInfo(String groupName) throws MmdFormatException;\r
-\r
-    /**\r
-     * ボーングループ内訳の通知を受け取る。\r
-     * {@link #GROUPEDBONE_LIST}ループの構成要素。\r
-     * @param boneId グループに所属するボーンのID\r
-     * @param groupId ボーンが所属するボーングループIDに1を足した数\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdGroupedBoneInfo(int boneId, int groupId)\r
-            throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD bone information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの各種ボーン情報の通知用ハンドラ。
+ * ボーン定義の出現順と、0から始まるボーンIDは対応する。
+ */
+public interface PmdBoneHandler extends LoopHandler {
+
+    /**
+     * ボーン情報パースステージ。
+     */
+    class PmdBoneStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdBoneStage(){ super(); return; }
+    }
+
+    /** ボーン定義抽出ループ。 */
+    PmdBoneStage BONE_LIST = new PmdBoneStage();
+
+    /** IKリスト抽出ループ。 */
+    PmdBoneStage IK_LIST = new PmdBoneStage();
+
+    /** IKチェーンリスト抽出ループ。 */
+    PmdBoneStage IKCHAIN_LIST = new PmdBoneStage();
+
+    /** ボーングループ名抽出ループ。 */
+    PmdBoneStage BONEGROUP_LIST = new PmdBoneStage();
+
+    /** ボーングループ内訳抽出ループ。 */
+    PmdBoneStage GROUPEDBONE_LIST = new PmdBoneStage();
+
+    /**
+     * ボーン定義情報の通知を受け取る。
+     * {@link #BONE_LIST}ループの構成要素。
+     * @param boneName ボーン名
+     * @param boneKind ボーン種別。
+     * <ul>
+     * <li>0:回転
+     * <li>1:回転/移動
+     * <li>2:IK
+     * <li>3:不明
+     * <li>4:IK影響下(回転)
+     * <li>5:回転影響下
+     * <li>6:IK接続先
+     * <li>7:非表示
+     * <li>8:捩り
+     * <li>9:回転連動
+     * </ul>
+     * ※8,9はMMD4.0から?
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdBoneInfo(String boneName, byte boneKind)
+            throws MmdFormatException;
+
+    /**
+     * ボーン間接続情報の通知を受け取る。
+     * {@link #BONE_LIST}ループの構成要素。
+     * @param parentId 親(前)ボーンID。無い場合は0xffff。
+     * @param tailId 子(次)ボーンID。末端の場合は0。
+     * 捩りボーンの場合は軸方向のボーンID、
+     * 回転連動ボーンの場合は影響元ボーンID
+     * @param ikId 影響IKボーンID。未指定の場合は0。
+     * ※回転連動では影響度(0-100)、負や100以上もOK!
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdBoneLink(int parentId, int tailId, int ikId)
+            throws MmdFormatException;
+
+    /**
+     * ボーン位置情報の通知を受け取る。
+     * {@link #BONE_LIST}ループの構成要素。
+     * @param xPos X座標
+     * @param yPos Y座標
+     * @param zPos Z座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdBonePosition(float xPos, float yPos, float zPos)
+            throws MmdFormatException;
+
+    /**
+     * IKボーン情報の通知を受け取る。
+     * {@link #IK_LIST}ループの構成要素。
+     * @param boneId IKボーンID
+     * @param targetId IKボーンが最初に接続するIK接続先ボーンID
+     * @param depth 再帰演算の深さ
+     * @param weight 制限角度強度
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdIKInfo(int boneId, int targetId, int depth, float weight)
+            throws MmdFormatException;
+
+    /**
+     * IKチェイン要素の通知を受け取る。
+     * {@link #IK_LIST}ループの下位{@link #IKCHAIN_LIST}ループの構成要素。
+     * @param childId IK影響下ボーンID
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdIKChainInfo(int childId)
+            throws MmdFormatException;
+
+    /**
+     * ボーングループ名定義の通知を受け取る。
+     * {@link #BONEGROUP_LIST}ループの構成要素。
+     * @param groupName ボーングループ名。末尾のLF(0x0a)は削除される。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdBoneGroupInfo(String groupName) throws MmdFormatException;
+
+    /**
+     * ボーングループ内訳の通知を受け取る。
+     * {@link #GROUPEDBONE_LIST}ループの構成要素。
+     * @param boneId グループに所属するボーンのID
+     * @param groupId ボーンが所属するボーングループIDに1を足した数
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdGroupedBoneInfo(int boneId, int groupId)
+            throws MmdFormatException;
+
+}
index 0a26bc9..017d47d 100644 (file)
@@ -1,82 +1,82 @@
-/*\r
- * PMD english information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの英語情報の通知用ハンドラ。\r
- */\r
-public interface PmdEngHandler extends LoopHandler {\r
-\r
-    /**\r
-     * 英語情報パースステージ。\r
-     */\r
-    class PmdEngStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdEngStage(){ super(); return; }\r
-    }\r
-\r
-    /** ボーン英語名抽出ループ。 */\r
-    ParseStage ENGBONE_LIST = new PmdEngStage();\r
-\r
-    /** モーフ英語名抽出ループ。 */\r
-    ParseStage ENGMORPH_LIST = new PmdEngStage();\r
-\r
-    /** ボーングループ英語名抽出グループ。 */\r
-    ParseStage ENGBONEGROUP_LIST = new PmdEngStage();\r
-\r
-    /**\r
-     * PMD英語情報の有無の通知を受け取る。\r
-     * @param hasEnglishInfo 英語情報が含まれればtrue\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdEngEnabled(boolean hasEnglishInfo) throws MmdFormatException;\r
-\r
-    /**\r
-     * PMD英語基本情報の通知を受け取る。\r
-     * @param modelName モデル名\r
-     * @param description モデルの説明文。改行CRLFは"\n"に変換される。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdEngModelInfo(String modelName, String description)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 英語ボーン名の通知を受け取る。\r
-     * {@link #ENGBONE_LIST}ループの構成要素\r
-     * @param boneName 英語ボーン名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdEngBoneInfo(String boneName) throws MmdFormatException;\r
-\r
-    /**\r
-     * 英語モーフ名の通知を受け取る。\r
-     * モーフ名「base」に対応する英語名は通知されない。\r
-     * {@link #ENGMORPH_LIST}ループの構成要素\r
-     * @param morphName 英語モーフ名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdEngMorphInfo(String morphName) throws MmdFormatException;\r
-\r
-    /**\r
-     * 英語ボーングループ名の通知を受け取る。\r
-     * {@link #ENGBONEGROUP_LIST}ループの構成要素\r
-     * @param groupName 英語ボーングループ名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdEngBoneGroupInfo(String groupName) throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD english information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの英語情報の通知用ハンドラ。
+ */
+public interface PmdEngHandler extends LoopHandler {
+
+    /**
+     * 英語情報パースステージ。
+     */
+    class PmdEngStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdEngStage(){ super(); return; }
+    }
+
+    /** ボーン英語名抽出ループ。 */
+    ParseStage ENGBONE_LIST = new PmdEngStage();
+
+    /** モーフ英語名抽出ループ。 */
+    ParseStage ENGMORPH_LIST = new PmdEngStage();
+
+    /** ボーングループ英語名抽出グループ。 */
+    ParseStage ENGBONEGROUP_LIST = new PmdEngStage();
+
+    /**
+     * PMD英語情報の有無の通知を受け取る。
+     * @param hasEnglishInfo 英語情報が含まれればtrue
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdEngEnabled(boolean hasEnglishInfo) throws MmdFormatException;
+
+    /**
+     * PMD英語基本情報の通知を受け取る。
+     * @param modelName モデル名
+     * @param description モデルの説明文。改行CRLFは"\n"に変換される。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdEngModelInfo(String modelName, String description)
+            throws MmdFormatException;
+
+    /**
+     * 英語ボーン名の通知を受け取る。
+     * {@link #ENGBONE_LIST}ループの構成要素
+     * @param boneName 英語ボーン名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdEngBoneInfo(String boneName) throws MmdFormatException;
+
+    /**
+     * 英語モーフ名の通知を受け取る。
+     * モーフ名「base」に対応する英語名は通知されない。
+     * {@link #ENGMORPH_LIST}ループの構成要素
+     * @param morphName 英語モーフ名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdEngMorphInfo(String morphName) throws MmdFormatException;
+
+    /**
+     * 英語ボーングループ名の通知を受け取る。
+     * {@link #ENGBONEGROUP_LIST}ループの構成要素
+     * @param groupName 英語ボーングループ名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdEngBoneGroupInfo(String groupName) throws MmdFormatException;
+
+}
index 70567f9..be000c5 100644 (file)
-/*\r
- * PMD joint information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの各種剛体間ジョイント情報の通知用ハンドラ。\r
- */\r
-public interface PmdJointHandler extends LoopHandler {\r
-\r
-    /**\r
-     * ジョイント情報パースステージ。\r
-     */\r
-    class PmdJointStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdJointStage(){ super(); return; }\r
-    }\r
-\r
-    /** ジョイント情報抽出ループ。 */\r
-    PmdJointStage JOINT_LIST = new PmdJointStage();\r
-\r
-    /**\r
-     * ジョイント名の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param jointName ジョイント名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdJointName(String jointName)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイントが繋ぐ接続剛体IDの通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param rigidIdA 接続剛体AのID\r
-     * @param rigidIdB 接続剛体BのID\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdJointLink(int rigidIdA, int rigidIdB)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイント位置の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param posX X座標\r
-     * @param posY Y座標\r
-     * @param posZ Z座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdJointPosition(float posX, float posY, float posZ)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイント回転姿勢の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param radX X軸回転量(radian)\r
-     * @param radY Y軸回転量(radian)\r
-     * @param radZ Z軸回転量(radian)\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdJointRotation(float radX, float radY, float radZ)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイント移動制限の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * ※(制限端その1<=その2)条件を満たす必要はあるか?\r
-     * @param posXlim1 X座標制限端その1\r
-     * @param posXlim2 X座標制限端その2\r
-     * @param posYlim1 Y座標制限端その1\r
-     * @param posYlim2 Y座標制限端その2\r
-     * @param posZlim1 Z座標制限端その1\r
-     * @param posZlim2 Z座標制限端その2\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdPositionLimit(float posXlim1, float posXlim2,\r
-                            float posYlim1, float posYlim2,\r
-                            float posZlim1, float posZlim2 )\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイント回転制限の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * ※(制限端その1<=その2)条件を満たす必要はあるか?\r
-     * @param radXlim1 X軸制限端その1(radian)\r
-     * @param radXlim2 X軸制限端その2(radian)\r
-     * @param radYlim1 Y軸制限端その1(radian)\r
-     * @param radYlim2 Y軸制限端その2(radian)\r
-     * @param radZlim1 Z軸制限端その1(radian)\r
-     * @param radZlim2 Z軸制限端その2(radian)\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdRotationLimit(float radXlim1, float radXlim2,\r
-                            float radYlim1, float radYlim2,\r
-                            float radZlim1, float radZlim2 )\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイントのばね移動情報の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param elasticPosX X座標\r
-     * @param elasticPosY Y座標\r
-     * @param elasticPosZ Z座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdElasticPosition(float elasticPosX,\r
-                               float elasticPosY,\r
-                               float elasticPosZ )\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * ジョイントのばね回転情報の通知を受け取る。\r
-     * {@link #JOINT_LIST}ループの構成要素。\r
-     * @param elasticDegX X軸変量(degree)\r
-     * @param elasticDegY Y軸変量(degree)\r
-     * @param elasticDegZ Z軸変量(degree)\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示。\r
-     */\r
-    void pmdElasticRotation(float elasticDegX,\r
-                               float elasticDegY,\r
-                               float elasticDegZ )\r
-        throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD joint information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの各種剛体間ジョイント情報の通知用ハンドラ。
+ */
+public interface PmdJointHandler extends LoopHandler {
+
+    /**
+     * ジョイント情報パースステージ。
+     */
+    class PmdJointStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdJointStage(){ super(); return; }
+    }
+
+    /** ジョイント情報抽出ループ。 */
+    PmdJointStage JOINT_LIST = new PmdJointStage();
+
+    /**
+     * ジョイント名の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param jointName ジョイント名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdJointName(String jointName)
+        throws MmdFormatException;
+
+    /**
+     * ジョイントが繋ぐ接続剛体IDの通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param rigidIdA 接続剛体AのID
+     * @param rigidIdB 接続剛体BのID
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdJointLink(int rigidIdA, int rigidIdB)
+        throws MmdFormatException;
+
+    /**
+     * ジョイント位置の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param posX X座標
+     * @param posY Y座標
+     * @param posZ Z座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdJointPosition(float posX, float posY, float posZ)
+        throws MmdFormatException;
+
+    /**
+     * ジョイント回転姿勢の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param radX X軸回転量(radian)
+     * @param radY Y軸回転量(radian)
+     * @param radZ Z軸回転量(radian)
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdJointRotation(float radX, float radY, float radZ)
+        throws MmdFormatException;
+
+    /**
+     * ジョイント移動制限の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * ※(制限端その1<=その2)条件を満たす必要はあるか?
+     * @param posXlim1 X座標制限端その1
+     * @param posXlim2 X座標制限端その2
+     * @param posYlim1 Y座標制限端その1
+     * @param posYlim2 Y座標制限端その2
+     * @param posZlim1 Z座標制限端その1
+     * @param posZlim2 Z座標制限端その2
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdPositionLimit(float posXlim1, float posXlim2,
+                            float posYlim1, float posYlim2,
+                            float posZlim1, float posZlim2 )
+        throws MmdFormatException;
+
+    /**
+     * ジョイント回転制限の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * ※(制限端その1<=その2)条件を満たす必要はあるか?
+     * @param radXlim1 X軸制限端その1(radian)
+     * @param radXlim2 X軸制限端その2(radian)
+     * @param radYlim1 Y軸制限端その1(radian)
+     * @param radYlim2 Y軸制限端その2(radian)
+     * @param radZlim1 Z軸制限端その1(radian)
+     * @param radZlim2 Z軸制限端その2(radian)
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdRotationLimit(float radXlim1, float radXlim2,
+                            float radYlim1, float radYlim2,
+                            float radZlim1, float radZlim2 )
+        throws MmdFormatException;
+
+    /**
+     * ジョイントのばね移動情報の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param elasticPosX X座標
+     * @param elasticPosY Y座標
+     * @param elasticPosZ Z座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdElasticPosition(float elasticPosX,
+                               float elasticPosY,
+                               float elasticPosZ )
+        throws MmdFormatException;
+
+    /**
+     * ジョイントのばね回転情報の通知を受け取る。
+     * {@link #JOINT_LIST}ループの構成要素。
+     * @param elasticDegX X軸変量(degree)
+     * @param elasticDegY Y軸変量(degree)
+     * @param elasticDegZ Z軸変量(degree)
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示。
+     */
+    void pmdElasticRotation(float elasticDegX,
+                               float elasticDegY,
+                               float elasticDegZ )
+        throws MmdFormatException;
+
+}
index 09daa2b..2f3ea53 100644 (file)
@@ -1,81 +1,81 @@
-/*\r
- * pmd limit numbers\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.CommonParser;\r
-\r
-/**\r
- * PMDファイルフォーマットの各種リミット値その他定数。\r
- */\r
-public final class PmdLimits {\r
-\r
-    /** モデル名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_MODELNAME = 20;\r
-\r
-    /** モデル説明文最大長。バイト単位。 */\r
-    public static final int MAXBYTES_MODELDESC = 256;\r
-\r
-    /** ボーン名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_BONENAME = 20;\r
-\r
-    /** モーフ名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_MORPHNAME = 20;\r
-\r
-    /** ボーングループ名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_BONEGROUPNAME = 50;\r
-\r
-    /** テクスチャファイル名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_TEXTUREFILENAME = 20;\r
-\r
-    /** 独自トゥーンテクスチャファイル名の最大長。バイト単位。 */\r
-    public static final int MAXBYTES_TOONFILENAME = 100;\r
-\r
-    /** 剛体名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_RIGIDNAME = 20;\r
-\r
-    /** ジョイント名最大長。バイト単位。 */\r
-    public static final int MAXBYTES_JOINTNAME = 20;\r
-\r
-\r
-    /**\r
-     * ボーン最大数。\r
-     * (Id : 0 - 0xfffe)\r
-     * MMDがいくつまで受け入れるかはまた別の話だよ。\r
-     */\r
-    public static final int MAX_BONE = 65535;\r
-\r
-    /** 剛体衝突グループ総数。 */\r
-    public static final int RIGIDGROUP_FIXEDNUM = 16;\r
-\r
-    /** 独自トゥーンテクスチャファイル名テーブルの固定数。 */\r
-    public static final int TOON_FIXEDNUM = 10;\r
-\r
-\r
-    static{\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MODELNAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MODELDESC;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_BONENAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MORPHNAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_BONEGROUPNAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_TEXTUREFILENAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_TOONFILENAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_RIGIDNAME;\r
-        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_JOINTNAME;\r
-    }\r
-\r
-\r
-    /**\r
-     * 隠しコンストラクタ。\r
-     */\r
-    private PmdLimits(){\r
-        super();\r
-        assert false;\r
-        throw new AssertionError();\r
-    }\r
-\r
-}\r
+/*
+ * pmd limit numbers
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.CommonParser;
+
+/**
+ * PMDファイルフォーマットの各種リミット値その他定数。
+ */
+public final class PmdLimits {
+
+    /** モデル名最大長。バイト単位。 */
+    public static final int MAXBYTES_MODELNAME = 20;
+
+    /** モデル説明文最大長。バイト単位。 */
+    public static final int MAXBYTES_MODELDESC = 256;
+
+    /** ボーン名最大長。バイト単位。 */
+    public static final int MAXBYTES_BONENAME = 20;
+
+    /** モーフ名最大長。バイト単位。 */
+    public static final int MAXBYTES_MORPHNAME = 20;
+
+    /** ボーングループ名最大長。バイト単位。 */
+    public static final int MAXBYTES_BONEGROUPNAME = 50;
+
+    /** テクスチャファイル名最大長。バイト単位。 */
+    public static final int MAXBYTES_TEXTUREFILENAME = 20;
+
+    /** 独自トゥーンテクスチャファイル名の最大長。バイト単位。 */
+    public static final int MAXBYTES_TOONFILENAME = 100;
+
+    /** 剛体名最大長。バイト単位。 */
+    public static final int MAXBYTES_RIGIDNAME = 20;
+
+    /** ジョイント名最大長。バイト単位。 */
+    public static final int MAXBYTES_JOINTNAME = 20;
+
+
+    /**
+     * ボーン最大数。
+     * (Id : 0 - 0xfffe)
+     * MMDがいくつまで受け入れるかはまた別の話だよ。
+     */
+    public static final int MAX_BONE = 65535;
+
+    /** 剛体衝突グループ総数。 */
+    public static final int RIGIDGROUP_FIXEDNUM = 16;
+
+    /** 独自トゥーンテクスチャファイル名テーブルの固定数。 */
+    public static final int TOON_FIXEDNUM = 10;
+
+
+    static{
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MODELNAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MODELDESC;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_BONENAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_MORPHNAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_BONEGROUPNAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_TEXTUREFILENAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_TOONFILENAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_RIGIDNAME;
+        assert CommonParser.TEXTBUF_SZ >= MAXBYTES_JOINTNAME;
+    }
+
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private PmdLimits(){
+        super();
+        assert false;
+        throw new AssertionError();
+    }
+
+}
index f0d51f7..4944546 100644 (file)
-/*\r
- * PMD material information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの各種材質情報の通知用ハンドラ。\r
- * 色空間はsRGB?\r
- */\r
-public interface PmdMaterialHandler extends LoopHandler {\r
-\r
-    /**\r
-     * モデル材質パースステージ。\r
-     */\r
-    class PmdMaterialStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdMaterialStage(){ super(); return; }\r
-    }\r
-\r
-    /** 材質抽出ループ。 */\r
-    PmdMaterialStage MATERIAL_LIST = new PmdMaterialStage();\r
-\r
-    /**\r
-     * 材質の拡散光成分の通知を受け取る。\r
-     * {@link #MATERIAL_LIST}ループの構成要素。\r
-     * @param red 0.0~1.0の範囲の赤成分\r
-     * @param green 0.0~1.0の範囲の緑成分\r
-     * @param blue 0.0~1.0の範囲の青成分\r
-     * @param alpha 0.0(透明)~1.0(不透明)のアルファ値。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMaterialDiffuse(float red, float green, float blue,\r
-                               float alpha )\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 材質の反射光成分の通知を受け取る。\r
-     * {@link #MATERIAL_LIST}ループの構成要素。\r
-     * @param red 0.0~1.0の範囲の赤成分\r
-     * @param green 0.0~1.0の範囲の緑成分\r
-     * @param blue 0.0~1.0の範囲の青成分\r
-     * @param shininess 光沢強度(1~15ぐらい)\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMaterialSpecular(float red, float green, float blue,\r
-                                float shininess)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 材質の環境色成分の通知を受け取る。\r
-     * {@link #MATERIAL_LIST}ループの構成要素。\r
-     * @param red 0.0~1.0の範囲の赤成分\r
-     * @param green 0.0~1.0の範囲の緑成分\r
-     * @param blue 0.0~1.0の範囲の青成分\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMaterialAmbient(float red, float green, float blue)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * シェーディング情報の通知を受け取る。\r
-     * {@link #MATERIAL_LIST}ループの構成要素。\r
-     * @param toonIdx トゥーンファイル番号。\r
-     * 0ならtoon01.bmp。9ならtoon10.bmp。0xffならtoon0.bmp。\r
-     * @param textureFile テクスチャファイル名。\r
-     * 無ければ空文字。\r
-     * @param sphereFile スフィアマップファイル名。\r
-     * 無ければ空文字。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMaterialShading(int toonIdx,\r
-                               String textureFile, String sphereFile )\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 材質情報の通知を受け取る。\r
-     * {@link #MATERIAL_LIST}ループの構成要素。\r
-     * @param hasEdge エッジを表示するならtrue\r
-     * @param vertexNum 面頂点数。\r
-     * 3の倍数のはず。\r
-     * 3で割ると積算で表される面IDの範囲を表す。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMaterialInfo(boolean hasEdge, int vertexNum)\r
-            throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD material information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの各種材質情報の通知用ハンドラ。
+ * 色空間はsRGB?
+ */
+public interface PmdMaterialHandler extends LoopHandler {
+
+    /**
+     * モデル材質パースステージ。
+     */
+    class PmdMaterialStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdMaterialStage(){ super(); return; }
+    }
+
+    /** 材質抽出ループ。 */
+    PmdMaterialStage MATERIAL_LIST = new PmdMaterialStage();
+
+    /**
+     * 材質の拡散光成分の通知を受け取る。
+     * {@link #MATERIAL_LIST}ループの構成要素。
+     * @param red 0.0~1.0の範囲の赤成分
+     * @param green 0.0~1.0の範囲の緑成分
+     * @param blue 0.0~1.0の範囲の青成分
+     * @param alpha 0.0(透明)~1.0(不透明)のアルファ値。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMaterialDiffuse(float red, float green, float blue,
+                               float alpha )
+            throws MmdFormatException;
+
+    /**
+     * 材質の反射光成分の通知を受け取る。
+     * {@link #MATERIAL_LIST}ループの構成要素。
+     * @param red 0.0~1.0の範囲の赤成分
+     * @param green 0.0~1.0の範囲の緑成分
+     * @param blue 0.0~1.0の範囲の青成分
+     * @param shininess 光沢強度(1~15ぐらい)
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMaterialSpecular(float red, float green, float blue,
+                                float shininess)
+            throws MmdFormatException;
+
+    /**
+     * 材質の環境色成分の通知を受け取る。
+     * {@link #MATERIAL_LIST}ループの構成要素。
+     * @param red 0.0~1.0の範囲の赤成分
+     * @param green 0.0~1.0の範囲の緑成分
+     * @param blue 0.0~1.0の範囲の青成分
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMaterialAmbient(float red, float green, float blue)
+            throws MmdFormatException;
+
+    /**
+     * シェーディング情報の通知を受け取る。
+     * {@link #MATERIAL_LIST}ループの構成要素。
+     * @param toonIdx トゥーンファイル番号。
+     * 0ならtoon01.bmp。9ならtoon10.bmp。0xffならtoon0.bmp。
+     * @param textureFile テクスチャファイル名。
+     * 無ければ空文字。
+     * @param sphereFile スフィアマップファイル名。
+     * 無ければ空文字。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMaterialShading(int toonIdx,
+                               String textureFile, String sphereFile )
+            throws MmdFormatException;
+
+    /**
+     * 材質情報の通知を受け取る。
+     * {@link #MATERIAL_LIST}ループの構成要素。
+     * @param hasEdge エッジを表示するならtrue
+     * @param vertexNum 面頂点数。
+     * 3の倍数のはず。
+     * 3で割ると積算で表される面IDの範囲を表す。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMaterialInfo(boolean hasEdge, int vertexNum)
+            throws MmdFormatException;
+
+}
index eb36cd3..c3efed6 100644 (file)
@@ -1,77 +1,77 @@
-/*\r
- * PMD morph information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルのモーフ情報の通知用ハンドラ。\r
- */\r
-public interface PmdMorphHandler extends LoopHandler {\r
-\r
-    /**\r
-     * モーフ情報パースステージ。\r
-     */\r
-    class PmdMorphStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdMorphStage(){ super(); return; }\r
-    }\r
-\r
-    /** モーフ抽出ループ。 */\r
-    PmdMorphStage MORPH_LIST = new PmdMorphStage();\r
-\r
-    /** モーフ頂点抽出ループ。 */\r
-    PmdMorphStage MORPHVERTEX_LIST = new PmdMorphStage();\r
-\r
-    /** モーフ出現順抽出ループ。 */\r
-    PmdMorphStage MORPHORDER_LIST = new PmdMorphStage();\r
-\r
-    /**\r
-     * モーフ情報の通知を受け取る。\r
-     * {@link #MORPH_LIST}ループの構成要素\r
-     * @param morphName モーフ名\r
-     * @param morphType モーフ種別。\r
-     * <ul>\r
-     * <li>0:base\r
-     * <li>1:まゆ\r
-     * <li>2:目\r
-     * <li>3:リップ\r
-     * <li>4:その他\r
-     * </ul>\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMorphInfo(String morphName, byte morphType)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * モーフ形状の通知を受け取る。\r
-     * {@link #MORPH_LIST}ループの下位{@link #MORPHVERTEX_LIST}の構成要素\r
-     * @param serialId base型の場合は頂点ID、それ以外はモーフ頂点ID\r
-     * @param xPos base型の場合はX座標、それ以外はX軸変位\r
-     * @param yPos base型の場合はY座標、それ以外はY軸変位\r
-     * @param zPos base型の場合はZ座標、それ以外はZ軸変位\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMorphVertexInfo(int serialId,\r
-                               float xPos, float yPos, float zPos)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 各モーフ種別内のGUI表示順の通知を受け取る。\r
-     * {@link #MORPHORDER_LIST}ループの構成要素\r
-     * @param morphId モーフ通し番号。同一種別内の大小関係のみ意味がある。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdMorphOrderInfo(int morphId) throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD morph information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルのモーフ情報の通知用ハンドラ。
+ */
+public interface PmdMorphHandler extends LoopHandler {
+
+    /**
+     * モーフ情報パースステージ。
+     */
+    class PmdMorphStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdMorphStage(){ super(); return; }
+    }
+
+    /** モーフ抽出ループ。 */
+    PmdMorphStage MORPH_LIST = new PmdMorphStage();
+
+    /** モーフ頂点抽出ループ。 */
+    PmdMorphStage MORPHVERTEX_LIST = new PmdMorphStage();
+
+    /** モーフ出現順抽出ループ。 */
+    PmdMorphStage MORPHORDER_LIST = new PmdMorphStage();
+
+    /**
+     * モーフ情報の通知を受け取る。
+     * {@link #MORPH_LIST}ループの構成要素
+     * @param morphName モーフ名
+     * @param morphType モーフ種別。
+     * <ul>
+     * <li>0:base
+     * <li>1:まゆ
+     * <li>2:目
+     * <li>3:リップ
+     * <li>4:その他
+     * </ul>
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMorphInfo(String morphName, byte morphType)
+            throws MmdFormatException;
+
+    /**
+     * モーフ形状の通知を受け取る。
+     * {@link #MORPH_LIST}ループの下位{@link #MORPHVERTEX_LIST}の構成要素
+     * @param serialId base型の場合は頂点ID、それ以外はモーフ頂点ID
+     * @param xPos base型の場合はX座標、それ以外はX軸変位
+     * @param yPos base型の場合はY座標、それ以外はY軸変位
+     * @param zPos base型の場合はZ座標、それ以外はZ軸変位
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMorphVertexInfo(int serialId,
+                               float xPos, float yPos, float zPos)
+            throws MmdFormatException;
+
+    /**
+     * 各モーフ種別内のGUI表示順の通知を受け取る。
+     * {@link #MORPHORDER_LIST}ループの構成要素
+     * @param morphId モーフ通し番号。同一種別内の大小関係のみ意味がある。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdMorphOrderInfo(int morphId) throws MmdFormatException;
+
+}
index ca77571..5889b72 100644 (file)
@@ -1,29 +1,29 @@
-/*\r
- * pmd file parser (up to date)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-\r
-/**\r
- * PMDモデルファイルのパーサ最新版。\r
- * 将来のリリースにおいて、\r
- * 常に最新のPMDモデルファイルフォーマットに対応したパーサの\r
- * 別名であることが保証される。つもり。\r
- */\r
-public class PmdParser extends PmdParserExt3{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public PmdParser(MmdSource source){\r
-        super(source);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * pmd file parser (up to date)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.MmdSource;
+
+/**
+ * PMDモデルファイルのパーサ最新版。
+ * 将来のリリースにおいて、
+ * 常に最新のPMDモデルファイルフォーマットに対応したパーサの
+ * 別名であることが保証される。つもり。
+ */
+public class PmdParser extends PmdParserExt3{
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public PmdParser(MmdSource source){
+        super(source);
+        return;
+    }
+
+}
index 8a45f6b..c505d67 100644 (file)
-/*\r
- * pmd file parser\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import java.io.IOException;\r
-import jp.sourceforge.mikutoga.parser.CommonParser;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-\r
-/**\r
- * PMDモデルファイルのパーサ基本部。\r
- */\r
-public class PmdParserBase extends CommonParser {\r
-\r
-    /** 改行文字列 CR。 */\r
-    protected static final String CR = "\r";       // 0x0d\r
-    /** 改行文字列 LF。 */\r
-    protected static final String LF = "\n";       // 0x0a\r
-    /** 改行文字列 CRLF。 */\r
-    protected static final String CRLF = CR + LF;  // 0x0d, 0x0a\r
-\r
-    private static final String MAGIC = "Pmd";\r
-    private static final int MAGIC_SZ = MAGIC.getBytes(CS_WIN31J).length;\r
-\r
-    private static final int VERTEX_DATA_SZ      = 38;\r
-    private static final int SURFACE_DATA_SZ     =  6;\r
-    private static final int MATERIAL_DATA_SZ    = 70;\r
-    private static final int BONE_DATA_SZ        = 39;\r
-    private static final int MORPHVERTEX_DATA_SZ = 16;\r
-    private static final int MORPHORDER_DATA_SZ  =  2;\r
-    private static final int BONEGROUP_DATA_SZ   = 50;\r
-    private static final int GROUPEDBONE_DATA_SZ =  3;\r
-\r
-\r
-    private PmdBasicHandler basicHandler = null;\r
-    private PmdShapeHandler shapeHandler = null;\r
-    private PmdMaterialHandler materialHandler = null;\r
-    private PmdBoneHandler boneHandler = null;\r
-    private PmdMorphHandler morphHandler = null;\r
-\r
-    private int boneCount      = -1;\r
-    private int morphCount     = -1;\r
-    private int boneGroupCount = -1;\r
-\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public PmdParserBase(MmdSource source){\r
-        super(source);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 文字列の最後がLF(0x0a)の場合削除する。\r
-     * @param name 文字列\r
-     * @return 末尾LFが削除された文字列\r
-     */\r
-    public static String chopLastLF(String name){\r
-        String result;\r
-\r
-        if(name.endsWith(LF)){\r
-            result = name.substring(0, name.length() - 1);\r
-        }else{\r
-            result = name;\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * シェーディング用ファイル情報から\r
-     * テクスチャファイル名とスフィアマップファイル名を分離する。\r
-     * @param shadingFile シェーディング用ファイル情報\r
-     * @return [0]:テクスチャファイル名 [1]:スフィアマップファイル名。\r
-     * 該当ファイル名が無い場合は空文字列。\r
-     */\r
-    public static String[] splitShadingFileInfo(String shadingFile){\r
-        String[] result;\r
-\r
-        result = shadingFile.split('\\'+"*", 2);\r
-        assert result.length == 1 || result.length == 2;\r
-\r
-        if(result.length == 1){\r
-            String onlyFile = result[0];\r
-            result = new String[2];\r
-            result[0] = "";\r
-            result[1] = "";\r
-            if(onlyFile.endsWith(".sph") || onlyFile.endsWith(".spa")){\r
-                result[1] = onlyFile;\r
-            }else{\r
-                result[0] = onlyFile;\r
-            }\r
-        }\r
-\r
-        assert result.length == 2;\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 基本情報通知ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setBasicHandler(PmdBasicHandler handler){\r
-        this.basicHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 形状情報通知ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setShapeHandler(PmdShapeHandler handler){\r
-        this.shapeHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 材質情報通知ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setMaterialHandler(PmdMaterialHandler handler){\r
-        this.materialHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーン情報通知ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setBoneHandler(PmdBoneHandler handler){\r
-        this.boneHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフ情報通知ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setMorphHandler(PmdMorphHandler handler){\r
-        this.morphHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * パースによって得られたボーン数を返す。\r
-     * @return ボーン数\r
-     */\r
-    protected int getBoneCount(){\r
-        return this.boneCount;\r
-    }\r
-\r
-    /**\r
-     * パースによって得られたモーフ数を返す。\r
-     * @return モーフ数\r
-     */\r
-    protected int getMorphCount(){\r
-        return this.morphCount;\r
-    }\r
-\r
-    /**\r
-     * パースによって得られたボーングループ数を返す。\r
-     * @return ボーングループ数\r
-     */\r
-    protected int getBoneGroupCount(){\r
-        return this.boneGroupCount;\r
-    }\r
-\r
-    /**\r
-     * PMDファイルのパースを開始する。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    public void parsePmd()\r
-            throws IOException, MmdFormatException {\r
-        if(this.basicHandler != null){\r
-            this.basicHandler.pmdParseStart();\r
-        }\r
-\r
-        parseBody();\r
-\r
-        boolean hasMoreData = hasMore();\r
-        if(this.basicHandler != null){\r
-            this.basicHandler.pmdParseEnd(hasMoreData);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイル本体のパースを開始する。\r
-     * パーサを拡張する場合はこのメソッドをオーバーライドする。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    protected void parseBody() throws IOException, MmdFormatException{\r
-        parsePmdHeader();\r
-\r
-        parseVertexList();\r
-        parseSurfaceList();\r
-        parseMaterialList();\r
-        parseBoneList();\r
-        parseIKList();\r
-        parseMorphList();\r
-        parseMorphOrderList();\r
-        parseBoneGroupList();\r
-        parseGroupedBoneList();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイルヘッダ部のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parsePmdHeader() throws IOException, MmdFormatException{\r
-        String magic = parseZeroTermString(MAGIC_SZ);\r
-        if( ! magic.equals(MAGIC) ){\r
-            throw new MmdFormatException("unrecognized magic data");\r
-        }\r
-\r
-        float ver = parseFloat();\r
-        String modelName   =\r
-                parseZeroTermString(PmdLimits.MAXBYTES_MODELNAME);\r
-        String description =\r
-                parseZeroTermString(PmdLimits.MAXBYTES_MODELDESC);\r
-        description = description.replace(CRLF, LF);\r
-\r
-        if(this.basicHandler != null){\r
-            this.basicHandler.pmdHeaderInfo(ver);\r
-            this.basicHandler.pmdModelInfo(modelName, description);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 頂点情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseVertexList() throws IOException, MmdFormatException{\r
-        int vertexNum = parseInteger();\r
-\r
-        if(this.shapeHandler == null){\r
-            skip(VERTEX_DATA_SZ * vertexNum);\r
-            return;\r
-        }\r
-\r
-        this.shapeHandler.loopStart(PmdShapeHandler.VERTEX_LIST, vertexNum);\r
-\r
-        for(int ct = 0; ct < vertexNum; ct++){\r
-            float xPos = parseFloat();\r
-            float yPos = parseFloat();\r
-            float zPos = parseFloat();\r
-            this.shapeHandler.pmdVertexPosition(xPos, yPos, zPos);\r
-\r
-            float xVec = parseFloat();\r
-            float yVec = parseFloat();\r
-            float zVec = parseFloat();\r
-            this.shapeHandler.pmdVertexNormal(xVec, yVec, zVec);\r
-\r
-            float uVal = parseFloat();\r
-            float vVal = parseFloat();\r
-            this.shapeHandler.pmdVertexUV(uVal, vVal);\r
-\r
-            int boneId1 = parseUShortAsInteger();\r
-            int boneId2 = parseUShortAsInteger();\r
-            int weightForB1 = parseUByteAsInteger();\r
-            this.shapeHandler.pmdVertexWeight(boneId1, boneId2, weightForB1);\r
-\r
-            boolean hideEdge = parseBoolean();\r
-            this.shapeHandler.pmdVertexEdge(hideEdge);\r
-\r
-            this.shapeHandler.loopNext(PmdShapeHandler.VERTEX_LIST);\r
-        }\r
-\r
-        this.shapeHandler.loopEnd(PmdShapeHandler.VERTEX_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 面情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseSurfaceList() throws IOException, MmdFormatException{\r
-        int vertexNum = parseInteger();\r
-        if(vertexNum % 3 != 0) throw new MmdFormatException();\r
-        int surfaceNum = vertexNum / 3;\r
-\r
-        if(this.shapeHandler == null){\r
-            skip(SURFACE_DATA_SZ * surfaceNum);\r
-            return;\r
-        }\r
-\r
-        this.shapeHandler.loopStart(PmdShapeHandler.SURFACE_LIST, surfaceNum);\r
-\r
-        for(int ct = 0; ct < surfaceNum; ct++){\r
-            int vertexId1 = parseUShortAsInteger();\r
-            int vertexId2 = parseUShortAsInteger();\r
-            int vertexId3 = parseUShortAsInteger();\r
-            this.shapeHandler.pmdSurfaceTriangle(vertexId1,\r
-                                                 vertexId2,\r
-                                                 vertexId3 );\r
-            this.shapeHandler.loopNext(PmdShapeHandler.SURFACE_LIST);\r
-        }\r
-\r
-        this.shapeHandler.loopEnd(PmdShapeHandler.SURFACE_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 材質情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseMaterialList() throws IOException, MmdFormatException{\r
-        int materialNum = parseInteger();\r
-\r
-        if(this.materialHandler == null){\r
-            skip(MATERIAL_DATA_SZ * materialNum);\r
-            return;\r
-        }\r
-\r
-        this.materialHandler.loopStart(PmdMaterialHandler.MATERIAL_LIST,\r
-                                       materialNum );\r
-\r
-        for(int ct = 0; ct < materialNum; ct++){\r
-            float red;\r
-            float green;\r
-            float blue;\r
-\r
-            red   = parseFloat();\r
-            green = parseFloat();\r
-            blue  = parseFloat();\r
-            float alpha = parseFloat();\r
-            this.materialHandler.pmdMaterialDiffuse(red, green, blue, alpha);\r
-\r
-            float shininess = parseFloat();\r
-            red   = parseFloat();\r
-            green = parseFloat();\r
-            blue  = parseFloat();\r
-            this.materialHandler.pmdMaterialSpecular(red, green, blue,\r
-                                                     shininess);\r
-\r
-            red   = parseFloat();\r
-            green = parseFloat();\r
-            blue  = parseFloat();\r
-            this.materialHandler.pmdMaterialAmbient(red, green, blue);\r
-\r
-            int toonidx = parseUByteAsInteger();\r
-            boolean hasEdge = parseBoolean();\r
-            int surfaceCount = parseInteger();\r
-            String shadingFile =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_TEXTUREFILENAME);\r
-            String[] splitted = splitShadingFileInfo(shadingFile);\r
-            String textureFile = splitted[0];\r
-            String sphereFile = splitted[1];\r
-\r
-            this.materialHandler.pmdMaterialShading(toonidx,\r
-                                                    textureFile, sphereFile );\r
-            this.materialHandler.pmdMaterialInfo(hasEdge, surfaceCount);\r
-\r
-            this.materialHandler.loopNext(PmdMaterialHandler.MATERIAL_LIST);\r
-        }\r
-\r
-        this.materialHandler.loopEnd(PmdMaterialHandler.MATERIAL_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーン情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseBoneList() throws IOException, MmdFormatException{\r
-        this.boneCount = parseUShortAsInteger();\r
-\r
-        if(this.boneHandler == null){\r
-            skip(BONE_DATA_SZ * this.boneCount);\r
-            return;\r
-        }\r
-\r
-        this.boneHandler.loopStart(PmdBoneHandler.BONE_LIST, this.boneCount);\r
-\r
-        for(int ct = 0; ct < this.boneCount; ct++){\r
-            String boneName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_BONENAME);\r
-            int parentId = parseUShortAsInteger();\r
-            int tailId = parseUShortAsInteger();\r
-            byte boneKind = parseByte();\r
-            int ikId = parseUShortAsInteger();\r
-\r
-            this.boneHandler.pmdBoneInfo(boneName, boneKind);\r
-            this.boneHandler.pmdBoneLink(parentId, tailId, ikId);\r
-\r
-            float xPos = parseFloat();\r
-            float yPos = parseFloat();\r
-            float zPos = parseFloat();\r
-\r
-            this.boneHandler.pmdBonePosition(xPos, yPos, zPos);\r
-\r
-            this.boneHandler.loopNext(PmdBoneHandler.BONE_LIST);\r
-        }\r
-\r
-        this.boneHandler.loopEnd(PmdBoneHandler.BONE_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKリスト情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseIKList() throws IOException, MmdFormatException{\r
-        int ikCount = parseUShortAsInteger();\r
-\r
-        if(this.boneHandler != null){\r
-            this.boneHandler.loopStart(PmdBoneHandler.IK_LIST, ikCount);\r
-        }\r
-\r
-        for(int ct = 0; ct < ikCount; ct++){\r
-            int boneId = parseUShortAsInteger();\r
-            int targetId = parseUShortAsInteger();\r
-            int chainLength = parseUByteAsInteger();\r
-            int depth = parseUShortAsInteger();\r
-            float weight = parseFloat();\r
-\r
-            parseIKChainList(chainLength);\r
-\r
-            if(this.boneHandler != null){\r
-                this.boneHandler.pmdIKInfo(boneId, targetId, depth, weight);\r
-                this.boneHandler.loopNext(PmdBoneHandler.IK_LIST);\r
-            }\r
-        }\r
-\r
-        if(this.boneHandler != null){\r
-            this.boneHandler.loopEnd(PmdBoneHandler.IK_LIST);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKチェーン情報のパースと通知。\r
-     * @param chainLength チェーン長\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseIKChainList(int chainLength)\r
-            throws IOException, MmdFormatException{\r
-        if(this.boneHandler != null){\r
-            this.boneHandler.loopStart(PmdBoneHandler.IKCHAIN_LIST,\r
-                                       chainLength);\r
-        }\r
-\r
-        for(int ct = 0; ct < chainLength; ct++){\r
-            int childId = parseUShortAsInteger();\r
-            if(this.boneHandler != null){\r
-                this.boneHandler.pmdIKChainInfo(childId);\r
-                this.boneHandler.loopNext(PmdBoneHandler.IKCHAIN_LIST);\r
-            }\r
-        }\r
-\r
-        if(this.boneHandler != null){\r
-            this.boneHandler.loopEnd(PmdBoneHandler.IKCHAIN_LIST);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフ情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseMorphList() throws IOException, MmdFormatException{\r
-        this.morphCount = parseUShortAsInteger();\r
-\r
-        if(this.morphHandler != null){\r
-            this.morphHandler.loopStart(PmdMorphHandler.MORPH_LIST,\r
-                                        this.morphCount );\r
-        }\r
-\r
-        for(int ct = 0; ct < this.morphCount; ct++){\r
-            String morphName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_MORPHNAME);\r
-            int vertexCount = parseInteger();\r
-            byte morphType = parseByte();\r
-\r
-            if(this.morphHandler != null){\r
-                this.morphHandler.pmdMorphInfo(morphName, morphType);\r
-            }\r
-\r
-            parseMorphVertexList(vertexCount);\r
-\r
-            if(this.morphHandler != null){\r
-                this.morphHandler.loopNext(PmdMorphHandler.MORPH_LIST);\r
-            }\r
-        }\r
-\r
-        if(this.morphHandler != null){\r
-            this.morphHandler.loopEnd(PmdMorphHandler.MORPH_LIST);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフ形状のパースと通知。\r
-     * @param vertexCount 頂点数\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseMorphVertexList(int vertexCount)\r
-            throws IOException, MmdFormatException{\r
-        if(this.morphHandler == null){\r
-            skip(MORPHVERTEX_DATA_SZ * vertexCount);\r
-            return;\r
-        }\r
-\r
-        this.morphHandler.loopStart(PmdMorphHandler.MORPHVERTEX_LIST,\r
-                                    vertexCount );\r
-\r
-        for(int ct = 0; ct < vertexCount; ct++){\r
-            int vertexId = parseInteger();\r
-            float xPos = parseFloat();\r
-            float yPos = parseFloat();\r
-            float zPos = parseFloat();\r
-            this.morphHandler.pmdMorphVertexInfo(vertexId, xPos, yPos, zPos);\r
-            this.morphHandler.loopNext(PmdMorphHandler.MORPHVERTEX_LIST);\r
-        }\r
-\r
-        this.morphHandler.loopEnd(PmdMorphHandler.MORPHVERTEX_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフGUI表示順のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseMorphOrderList()\r
-            throws IOException, MmdFormatException{\r
-        int morphOrderCount = parseUByteAsInteger();\r
-\r
-        if(this.morphHandler == null){\r
-            skip(MORPHORDER_DATA_SZ * morphOrderCount);\r
-            return;\r
-        }\r
-\r
-        this.morphHandler.loopStart(PmdMorphHandler.MORPHORDER_LIST,\r
-                                    morphOrderCount );\r
-\r
-        for(int ct = 0; ct < morphOrderCount; ct++){\r
-            int morphId = parseUShortAsInteger();\r
-            this.morphHandler.pmdMorphOrderInfo(morphId);\r
-\r
-            this.morphHandler.loopNext(PmdMorphHandler.MORPHORDER_LIST);\r
-        }\r
-\r
-        this.morphHandler.loopEnd(PmdMorphHandler.MORPHORDER_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーングループ名のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseBoneGroupList()\r
-            throws IOException, MmdFormatException{\r
-        this.boneGroupCount = parseUByteAsInteger();\r
-\r
-        if(this.boneHandler == null){\r
-            skip(BONEGROUP_DATA_SZ * this.boneGroupCount);\r
-            return;\r
-        }\r
-\r
-        this.boneHandler.loopStart(PmdBoneHandler.BONEGROUP_LIST,\r
-                                   this.boneGroupCount);\r
-\r
-        for(int ct = 0; ct < this.boneGroupCount; ct++){\r
-            String groupName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_BONEGROUPNAME);\r
-            groupName = chopLastLF(groupName);\r
-            this.boneHandler.pmdBoneGroupInfo(groupName);\r
-\r
-            this.boneHandler.loopNext(PmdBoneHandler.BONEGROUP_LIST);\r
-        }\r
-\r
-        this.boneHandler.loopEnd(PmdBoneHandler.BONEGROUP_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーングループ内訳のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseGroupedBoneList()\r
-            throws IOException, MmdFormatException{\r
-        int groupedBoneCount = parseInteger();\r
-\r
-        if(this.boneHandler == null){\r
-            skip(GROUPEDBONE_DATA_SZ * groupedBoneCount);\r
-            return;\r
-        }\r
-\r
-        this.boneHandler.loopStart(PmdBoneHandler.GROUPEDBONE_LIST,\r
-                                   groupedBoneCount);\r
-\r
-        for(int ct = 0; ct < groupedBoneCount; ct++){\r
-            int boneId = parseUShortAsInteger();\r
-            int groupId = parseUByteAsInteger();\r
-            this.boneHandler.pmdGroupedBoneInfo(boneId, groupId);\r
-\r
-            this.boneHandler.loopNext(PmdBoneHandler.GROUPEDBONE_LIST);\r
-        }\r
-\r
-        this.boneHandler.loopEnd(PmdBoneHandler.GROUPEDBONE_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * pmd file parser
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import java.io.IOException;
+import jp.sourceforge.mikutoga.parser.CommonParser;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+
+/**
+ * PMDモデルファイルのパーサ基本部。
+ */
+public class PmdParserBase extends CommonParser {
+
+    /** 改行文字列 CR。 */
+    protected static final String CR = "\r";       // 0x0d
+    /** 改行文字列 LF。 */
+    protected static final String LF = "\n";       // 0x0a
+    /** 改行文字列 CRLF。 */
+    protected static final String CRLF = CR + LF;  // 0x0d, 0x0a
+
+    private static final String MAGIC = "Pmd";
+    private static final int MAGIC_SZ = MAGIC.getBytes(CS_WIN31J).length;
+
+    private static final int VERTEX_DATA_SZ      = 38;
+    private static final int SURFACE_DATA_SZ     =  6;
+    private static final int MATERIAL_DATA_SZ    = 70;
+    private static final int BONE_DATA_SZ        = 39;
+    private static final int MORPHVERTEX_DATA_SZ = 16;
+    private static final int MORPHORDER_DATA_SZ  =  2;
+    private static final int BONEGROUP_DATA_SZ   = 50;
+    private static final int GROUPEDBONE_DATA_SZ =  3;
+
+
+    private PmdBasicHandler basicHandler = null;
+    private PmdShapeHandler shapeHandler = null;
+    private PmdMaterialHandler materialHandler = null;
+    private PmdBoneHandler boneHandler = null;
+    private PmdMorphHandler morphHandler = null;
+
+    private int boneCount      = -1;
+    private int morphCount     = -1;
+    private int boneGroupCount = -1;
+
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public PmdParserBase(MmdSource source){
+        super(source);
+        return;
+    }
+
+    /**
+     * 文字列の最後がLF(0x0a)の場合削除する。
+     * @param name 文字列
+     * @return 末尾LFが削除された文字列
+     */
+    public static String chopLastLF(String name){
+        String result;
+
+        if(name.endsWith(LF)){
+            result = name.substring(0, name.length() - 1);
+        }else{
+            result = name;
+        }
+
+        return result;
+    }
+
+    /**
+     * シェーディング用ファイル情報から
+     * テクスチャファイル名とスフィアマップファイル名を分離する。
+     * @param shadingFile シェーディング用ファイル情報
+     * @return [0]:テクスチャファイル名 [1]:スフィアマップファイル名。
+     * 該当ファイル名が無い場合は空文字列。
+     */
+    public static String[] splitShadingFileInfo(String shadingFile){
+        String[] result;
+
+        result = shadingFile.split('\\'+"*", 2);
+        assert result.length == 1 || result.length == 2;
+
+        if(result.length == 1){
+            String onlyFile = result[0];
+            result = new String[2];
+            result[0] = "";
+            result[1] = "";
+            if(onlyFile.endsWith(".sph") || onlyFile.endsWith(".spa")){
+                result[1] = onlyFile;
+            }else{
+                result[0] = onlyFile;
+            }
+        }
+
+        assert result.length == 2;
+
+        return result;
+    }
+
+    /**
+     * 基本情報通知ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setBasicHandler(PmdBasicHandler handler){
+        this.basicHandler = handler;
+        return;
+    }
+
+    /**
+     * 形状情報通知ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setShapeHandler(PmdShapeHandler handler){
+        this.shapeHandler = handler;
+        return;
+    }
+
+    /**
+     * 材質情報通知ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setMaterialHandler(PmdMaterialHandler handler){
+        this.materialHandler = handler;
+        return;
+    }
+
+    /**
+     * ボーン情報通知ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setBoneHandler(PmdBoneHandler handler){
+        this.boneHandler = handler;
+        return;
+    }
+
+    /**
+     * モーフ情報通知ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setMorphHandler(PmdMorphHandler handler){
+        this.morphHandler = handler;
+        return;
+    }
+
+    /**
+     * パースによって得られたボーン数を返す。
+     * @return ボーン数
+     */
+    protected int getBoneCount(){
+        return this.boneCount;
+    }
+
+    /**
+     * パースによって得られたモーフ数を返す。
+     * @return モーフ数
+     */
+    protected int getMorphCount(){
+        return this.morphCount;
+    }
+
+    /**
+     * パースによって得られたボーングループ数を返す。
+     * @return ボーングループ数
+     */
+    protected int getBoneGroupCount(){
+        return this.boneGroupCount;
+    }
+
+    /**
+     * PMDファイルのパースを開始する。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    public void parsePmd()
+            throws IOException, MmdFormatException {
+        if(this.basicHandler != null){
+            this.basicHandler.pmdParseStart();
+        }
+
+        parseBody();
+
+        boolean hasMoreData = hasMore();
+        if(this.basicHandler != null){
+            this.basicHandler.pmdParseEnd(hasMoreData);
+        }
+
+        return;
+    }
+
+    /**
+     * PMDファイル本体のパースを開始する。
+     * パーサを拡張する場合はこのメソッドをオーバーライドする。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    protected void parseBody() throws IOException, MmdFormatException{
+        parsePmdHeader();
+
+        parseVertexList();
+        parseSurfaceList();
+        parseMaterialList();
+        parseBoneList();
+        parseIKList();
+        parseMorphList();
+        parseMorphOrderList();
+        parseBoneGroupList();
+        parseGroupedBoneList();
+
+        return;
+    }
+
+    /**
+     * PMDファイルヘッダ部のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parsePmdHeader() throws IOException, MmdFormatException{
+        String magic = parseZeroTermString(MAGIC_SZ);
+        if( ! magic.equals(MAGIC) ){
+            throw new MmdFormatException("unrecognized magic data");
+        }
+
+        float ver = parseFloat();
+        String modelName   =
+                parseZeroTermString(PmdLimits.MAXBYTES_MODELNAME);
+        String description =
+                parseZeroTermString(PmdLimits.MAXBYTES_MODELDESC);
+        description = description.replace(CRLF, LF);
+
+        if(this.basicHandler != null){
+            this.basicHandler.pmdHeaderInfo(ver);
+            this.basicHandler.pmdModelInfo(modelName, description);
+        }
+
+        return;
+    }
+
+    /**
+     * 頂点情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseVertexList() throws IOException, MmdFormatException{
+        int vertexNum = parseInteger();
+
+        if(this.shapeHandler == null){
+            skip(VERTEX_DATA_SZ * vertexNum);
+            return;
+        }
+
+        this.shapeHandler.loopStart(PmdShapeHandler.VERTEX_LIST, vertexNum);
+
+        for(int ct = 0; ct < vertexNum; ct++){
+            float xPos = parseFloat();
+            float yPos = parseFloat();
+            float zPos = parseFloat();
+            this.shapeHandler.pmdVertexPosition(xPos, yPos, zPos);
+
+            float xVec = parseFloat();
+            float yVec = parseFloat();
+            float zVec = parseFloat();
+            this.shapeHandler.pmdVertexNormal(xVec, yVec, zVec);
+
+            float uVal = parseFloat();
+            float vVal = parseFloat();
+            this.shapeHandler.pmdVertexUV(uVal, vVal);
+
+            int boneId1 = parseUShortAsInteger();
+            int boneId2 = parseUShortAsInteger();
+            int weightForB1 = parseUByteAsInteger();
+            this.shapeHandler.pmdVertexWeight(boneId1, boneId2, weightForB1);
+
+            boolean hideEdge = parseBoolean();
+            this.shapeHandler.pmdVertexEdge(hideEdge);
+
+            this.shapeHandler.loopNext(PmdShapeHandler.VERTEX_LIST);
+        }
+
+        this.shapeHandler.loopEnd(PmdShapeHandler.VERTEX_LIST);
+
+        return;
+    }
+
+    /**
+     * 面情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseSurfaceList() throws IOException, MmdFormatException{
+        int vertexNum = parseInteger();
+        if(vertexNum % 3 != 0) throw new MmdFormatException();
+        int surfaceNum = vertexNum / 3;
+
+        if(this.shapeHandler == null){
+            skip(SURFACE_DATA_SZ * surfaceNum);
+            return;
+        }
+
+        this.shapeHandler.loopStart(PmdShapeHandler.SURFACE_LIST, surfaceNum);
+
+        for(int ct = 0; ct < surfaceNum; ct++){
+            int vertexId1 = parseUShortAsInteger();
+            int vertexId2 = parseUShortAsInteger();
+            int vertexId3 = parseUShortAsInteger();
+            this.shapeHandler.pmdSurfaceTriangle(vertexId1,
+                                                 vertexId2,
+                                                 vertexId3 );
+            this.shapeHandler.loopNext(PmdShapeHandler.SURFACE_LIST);
+        }
+
+        this.shapeHandler.loopEnd(PmdShapeHandler.SURFACE_LIST);
+
+        return;
+    }
+
+    /**
+     * 材質情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseMaterialList() throws IOException, MmdFormatException{
+        int materialNum = parseInteger();
+
+        if(this.materialHandler == null){
+            skip(MATERIAL_DATA_SZ * materialNum);
+            return;
+        }
+
+        this.materialHandler.loopStart(PmdMaterialHandler.MATERIAL_LIST,
+                                       materialNum );
+
+        for(int ct = 0; ct < materialNum; ct++){
+            float red;
+            float green;
+            float blue;
+
+            red   = parseFloat();
+            green = parseFloat();
+            blue  = parseFloat();
+            float alpha = parseFloat();
+            this.materialHandler.pmdMaterialDiffuse(red, green, blue, alpha);
+
+            float shininess = parseFloat();
+            red   = parseFloat();
+            green = parseFloat();
+            blue  = parseFloat();
+            this.materialHandler.pmdMaterialSpecular(red, green, blue,
+                                                     shininess);
+
+            red   = parseFloat();
+            green = parseFloat();
+            blue  = parseFloat();
+            this.materialHandler.pmdMaterialAmbient(red, green, blue);
+
+            int toonidx = parseUByteAsInteger();
+            boolean hasEdge = parseBoolean();
+            int surfaceCount = parseInteger();
+            String shadingFile =
+                    parseZeroTermString(PmdLimits.MAXBYTES_TEXTUREFILENAME);
+            String[] splitted = splitShadingFileInfo(shadingFile);
+            String textureFile = splitted[0];
+            String sphereFile = splitted[1];
+
+            this.materialHandler.pmdMaterialShading(toonidx,
+                                                    textureFile, sphereFile );
+            this.materialHandler.pmdMaterialInfo(hasEdge, surfaceCount);
+
+            this.materialHandler.loopNext(PmdMaterialHandler.MATERIAL_LIST);
+        }
+
+        this.materialHandler.loopEnd(PmdMaterialHandler.MATERIAL_LIST);
+
+        return;
+    }
+
+    /**
+     * ボーン情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseBoneList() throws IOException, MmdFormatException{
+        this.boneCount = parseUShortAsInteger();
+
+        if(this.boneHandler == null){
+            skip(BONE_DATA_SZ * this.boneCount);
+            return;
+        }
+
+        this.boneHandler.loopStart(PmdBoneHandler.BONE_LIST, this.boneCount);
+
+        for(int ct = 0; ct < this.boneCount; ct++){
+            String boneName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_BONENAME);
+            int parentId = parseUShortAsInteger();
+            int tailId = parseUShortAsInteger();
+            byte boneKind = parseByte();
+            int ikId = parseUShortAsInteger();
+
+            this.boneHandler.pmdBoneInfo(boneName, boneKind);
+            this.boneHandler.pmdBoneLink(parentId, tailId, ikId);
+
+            float xPos = parseFloat();
+            float yPos = parseFloat();
+            float zPos = parseFloat();
+
+            this.boneHandler.pmdBonePosition(xPos, yPos, zPos);
+
+            this.boneHandler.loopNext(PmdBoneHandler.BONE_LIST);
+        }
+
+        this.boneHandler.loopEnd(PmdBoneHandler.BONE_LIST);
+
+        return;
+    }
+
+    /**
+     * IKリスト情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseIKList() throws IOException, MmdFormatException{
+        int ikCount = parseUShortAsInteger();
+
+        if(this.boneHandler != null){
+            this.boneHandler.loopStart(PmdBoneHandler.IK_LIST, ikCount);
+        }
+
+        for(int ct = 0; ct < ikCount; ct++){
+            int boneId = parseUShortAsInteger();
+            int targetId = parseUShortAsInteger();
+            int chainLength = parseUByteAsInteger();
+            int depth = parseUShortAsInteger();
+            float weight = parseFloat();
+
+            parseIKChainList(chainLength);
+
+            if(this.boneHandler != null){
+                this.boneHandler.pmdIKInfo(boneId, targetId, depth, weight);
+                this.boneHandler.loopNext(PmdBoneHandler.IK_LIST);
+            }
+        }
+
+        if(this.boneHandler != null){
+            this.boneHandler.loopEnd(PmdBoneHandler.IK_LIST);
+        }
+
+        return;
+    }
+
+    /**
+     * IKチェーン情報のパースと通知。
+     * @param chainLength チェーン長
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseIKChainList(int chainLength)
+            throws IOException, MmdFormatException{
+        if(this.boneHandler != null){
+            this.boneHandler.loopStart(PmdBoneHandler.IKCHAIN_LIST,
+                                       chainLength);
+        }
+
+        for(int ct = 0; ct < chainLength; ct++){
+            int childId = parseUShortAsInteger();
+            if(this.boneHandler != null){
+                this.boneHandler.pmdIKChainInfo(childId);
+                this.boneHandler.loopNext(PmdBoneHandler.IKCHAIN_LIST);
+            }
+        }
+
+        if(this.boneHandler != null){
+            this.boneHandler.loopEnd(PmdBoneHandler.IKCHAIN_LIST);
+        }
+
+        return;
+    }
+
+    /**
+     * モーフ情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseMorphList() throws IOException, MmdFormatException{
+        this.morphCount = parseUShortAsInteger();
+
+        if(this.morphHandler != null){
+            this.morphHandler.loopStart(PmdMorphHandler.MORPH_LIST,
+                                        this.morphCount );
+        }
+
+        for(int ct = 0; ct < this.morphCount; ct++){
+            String morphName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_MORPHNAME);
+            int vertexCount = parseInteger();
+            byte morphType = parseByte();
+
+            if(this.morphHandler != null){
+                this.morphHandler.pmdMorphInfo(morphName, morphType);
+            }
+
+            parseMorphVertexList(vertexCount);
+
+            if(this.morphHandler != null){
+                this.morphHandler.loopNext(PmdMorphHandler.MORPH_LIST);
+            }
+        }
+
+        if(this.morphHandler != null){
+            this.morphHandler.loopEnd(PmdMorphHandler.MORPH_LIST);
+        }
+
+        return;
+    }
+
+    /**
+     * モーフ形状のパースと通知。
+     * @param vertexCount 頂点数
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseMorphVertexList(int vertexCount)
+            throws IOException, MmdFormatException{
+        if(this.morphHandler == null){
+            skip(MORPHVERTEX_DATA_SZ * vertexCount);
+            return;
+        }
+
+        this.morphHandler.loopStart(PmdMorphHandler.MORPHVERTEX_LIST,
+                                    vertexCount );
+
+        for(int ct = 0; ct < vertexCount; ct++){
+            int vertexId = parseInteger();
+            float xPos = parseFloat();
+            float yPos = parseFloat();
+            float zPos = parseFloat();
+            this.morphHandler.pmdMorphVertexInfo(vertexId, xPos, yPos, zPos);
+            this.morphHandler.loopNext(PmdMorphHandler.MORPHVERTEX_LIST);
+        }
+
+        this.morphHandler.loopEnd(PmdMorphHandler.MORPHVERTEX_LIST);
+
+        return;
+    }
+
+    /**
+     * モーフGUI表示順のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseMorphOrderList()
+            throws IOException, MmdFormatException{
+        int morphOrderCount = parseUByteAsInteger();
+
+        if(this.morphHandler == null){
+            skip(MORPHORDER_DATA_SZ * morphOrderCount);
+            return;
+        }
+
+        this.morphHandler.loopStart(PmdMorphHandler.MORPHORDER_LIST,
+                                    morphOrderCount );
+
+        for(int ct = 0; ct < morphOrderCount; ct++){
+            int morphId = parseUShortAsInteger();
+            this.morphHandler.pmdMorphOrderInfo(morphId);
+
+            this.morphHandler.loopNext(PmdMorphHandler.MORPHORDER_LIST);
+        }
+
+        this.morphHandler.loopEnd(PmdMorphHandler.MORPHORDER_LIST);
+
+        return;
+    }
+
+    /**
+     * ボーングループ名のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseBoneGroupList()
+            throws IOException, MmdFormatException{
+        this.boneGroupCount = parseUByteAsInteger();
+
+        if(this.boneHandler == null){
+            skip(BONEGROUP_DATA_SZ * this.boneGroupCount);
+            return;
+        }
+
+        this.boneHandler.loopStart(PmdBoneHandler.BONEGROUP_LIST,
+                                   this.boneGroupCount);
+
+        for(int ct = 0; ct < this.boneGroupCount; ct++){
+            String groupName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_BONEGROUPNAME);
+            groupName = chopLastLF(groupName);
+            this.boneHandler.pmdBoneGroupInfo(groupName);
+
+            this.boneHandler.loopNext(PmdBoneHandler.BONEGROUP_LIST);
+        }
+
+        this.boneHandler.loopEnd(PmdBoneHandler.BONEGROUP_LIST);
+
+        return;
+    }
+
+    /**
+     * ボーングループ内訳のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseGroupedBoneList()
+            throws IOException, MmdFormatException{
+        int groupedBoneCount = parseInteger();
+
+        if(this.boneHandler == null){
+            skip(GROUPEDBONE_DATA_SZ * groupedBoneCount);
+            return;
+        }
+
+        this.boneHandler.loopStart(PmdBoneHandler.GROUPEDBONE_LIST,
+                                   groupedBoneCount);
+
+        for(int ct = 0; ct < groupedBoneCount; ct++){
+            int boneId = parseUShortAsInteger();
+            int groupId = parseUByteAsInteger();
+            this.boneHandler.pmdGroupedBoneInfo(boneId, groupId);
+
+            this.boneHandler.loopNext(PmdBoneHandler.GROUPEDBONE_LIST);
+        }
+
+        this.boneHandler.loopEnd(PmdBoneHandler.GROUPEDBONE_LIST);
+
+        return;
+    }
+
+}
index cffe8d9..26fd3c8 100644 (file)
-/*\r
- * pmd parser extension 1\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import java.io.IOException;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-\r
-/**\r
- * PMDモデルファイルのパーサ拡張その1。\r
- * ※英名対応\r
- */\r
-public class PmdParserExt1 extends PmdParserBase {\r
-\r
-    private PmdEngHandler engHandler = null;\r
-    private boolean hasEnglishInfo = true;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public PmdParserExt1(MmdSource source){\r
-        super(source);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 英語ハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setEngHandler(PmdEngHandler handler){\r
-        this.engHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws MmdFormatException {@inheritDoc}\r
-     */\r
-    @Override\r
-    protected void parseBody()\r
-            throws IOException, MmdFormatException{\r
-        super.parseBody();\r
-\r
-        if(hasMore()){\r
-            parseEngHeader();\r
-            if(this.hasEnglishInfo){\r
-                parseEngBoneList();\r
-                parseEngMorphName();\r
-                parseEngBoneGroupName();\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDモデル英語基本情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseEngHeader()\r
-            throws IOException, MmdFormatException{\r
-        this.hasEnglishInfo = parseBoolean();\r
-\r
-        if(this.engHandler != null){\r
-            this.engHandler.pmdEngEnabled(this.hasEnglishInfo);\r
-        }\r
-        if( ! this.hasEnglishInfo ) return;\r
-\r
-        String modelName =\r
-                parseZeroTermString(PmdLimits.MAXBYTES_MODELNAME);\r
-        String description =\r
-                parseZeroTermString(PmdLimits.MAXBYTES_MODELDESC);\r
-        description = description.replace(CRLF, LF);\r
-\r
-        if(this.engHandler != null){\r
-            this.engHandler.pmdEngModelInfo(modelName, description);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDモデル英語ボーン名のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseEngBoneList()\r
-            throws IOException, MmdFormatException{\r
-        int boneNum = getBoneCount();\r
-\r
-        if(this.engHandler == null){\r
-            skip(PmdLimits.MAXBYTES_BONENAME * boneNum);\r
-            return;\r
-        }\r
-\r
-        this.engHandler.loopStart(PmdEngHandler.ENGBONE_LIST, boneNum);\r
-\r
-        for(int ct = 0; ct < boneNum; ct++){\r
-            String boneName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_BONENAME);\r
-            this.engHandler.pmdEngBoneInfo(boneName);\r
-\r
-            this.engHandler.loopNext(PmdEngHandler.ENGBONE_LIST);\r
-        }\r
-\r
-        this.engHandler.loopEnd(PmdEngHandler.ENGBONE_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDモデル英語モーフ名のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseEngMorphName()\r
-            throws IOException, MmdFormatException{\r
-        int morphNum = getMorphCount() - 1;  // base は英名なし\r
-\r
-        if(this.engHandler == null){\r
-            skip(PmdLimits.MAXBYTES_MORPHNAME * morphNum);\r
-            return;\r
-        }\r
-\r
-        this.engHandler.loopStart(PmdEngHandler.ENGMORPH_LIST, morphNum);\r
-\r
-        for(int ct = 0; ct < morphNum; ct++){\r
-            String morphName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_MORPHNAME);\r
-            this.engHandler.pmdEngMorphInfo(morphName);\r
-\r
-            this.engHandler.loopNext(PmdEngHandler.ENGMORPH_LIST);\r
-        }\r
-\r
-        this.engHandler.loopEnd(PmdEngHandler.ENGMORPH_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDモデル英語ボーングループ名のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseEngBoneGroupName()\r
-            throws IOException, MmdFormatException{\r
-        int groupNum = getBoneGroupCount();\r
-\r
-        if(this.engHandler == null){\r
-            skip(PmdLimits.MAXBYTES_BONEGROUPNAME * groupNum);\r
-            return;\r
-        }\r
-\r
-        this.engHandler.loopStart(PmdEngHandler.ENGBONEGROUP_LIST, groupNum);\r
-\r
-        for(int ct = 0; ct < groupNum; ct++){\r
-            String boneGroupName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_BONEGROUPNAME);\r
-            this.engHandler.pmdEngBoneGroupInfo(boneGroupName);\r
-\r
-            this.engHandler.loopNext(PmdEngHandler.ENGBONEGROUP_LIST);\r
-        }\r
-\r
-        this.engHandler.loopEnd(PmdEngHandler.ENGBONEGROUP_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * pmd parser extension 1
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import java.io.IOException;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+
+/**
+ * PMDモデルファイルのパーサ拡張その1。
+ * ※英名対応
+ */
+public class PmdParserExt1 extends PmdParserBase {
+
+    private PmdEngHandler engHandler = null;
+    private boolean hasEnglishInfo = true;
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public PmdParserExt1(MmdSource source){
+        super(source);
+        return;
+    }
+
+    /**
+     * 英語ハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setEngHandler(PmdEngHandler handler){
+        this.engHandler = handler;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdFormatException {@inheritDoc}
+     */
+    @Override
+    protected void parseBody()
+            throws IOException, MmdFormatException{
+        super.parseBody();
+
+        if(hasMore()){
+            parseEngHeader();
+            if(this.hasEnglishInfo){
+                parseEngBoneList();
+                parseEngMorphName();
+                parseEngBoneGroupName();
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * PMDモデル英語基本情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseEngHeader()
+            throws IOException, MmdFormatException{
+        this.hasEnglishInfo = parseBoolean();
+
+        if(this.engHandler != null){
+            this.engHandler.pmdEngEnabled(this.hasEnglishInfo);
+        }
+        if( ! this.hasEnglishInfo ) return;
+
+        String modelName =
+                parseZeroTermString(PmdLimits.MAXBYTES_MODELNAME);
+        String description =
+                parseZeroTermString(PmdLimits.MAXBYTES_MODELDESC);
+        description = description.replace(CRLF, LF);
+
+        if(this.engHandler != null){
+            this.engHandler.pmdEngModelInfo(modelName, description);
+        }
+
+        return;
+    }
+
+    /**
+     * PMDモデル英語ボーン名のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseEngBoneList()
+            throws IOException, MmdFormatException{
+        int boneNum = getBoneCount();
+
+        if(this.engHandler == null){
+            skip(PmdLimits.MAXBYTES_BONENAME * boneNum);
+            return;
+        }
+
+        this.engHandler.loopStart(PmdEngHandler.ENGBONE_LIST, boneNum);
+
+        for(int ct = 0; ct < boneNum; ct++){
+            String boneName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_BONENAME);
+            this.engHandler.pmdEngBoneInfo(boneName);
+
+            this.engHandler.loopNext(PmdEngHandler.ENGBONE_LIST);
+        }
+
+        this.engHandler.loopEnd(PmdEngHandler.ENGBONE_LIST);
+
+        return;
+    }
+
+    /**
+     * PMDモデル英語モーフ名のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseEngMorphName()
+            throws IOException, MmdFormatException{
+        int morphNum = getMorphCount() - 1;  // base は英名なし
+
+        if(this.engHandler == null){
+            skip(PmdLimits.MAXBYTES_MORPHNAME * morphNum);
+            return;
+        }
+
+        this.engHandler.loopStart(PmdEngHandler.ENGMORPH_LIST, morphNum);
+
+        for(int ct = 0; ct < morphNum; ct++){
+            String morphName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_MORPHNAME);
+            this.engHandler.pmdEngMorphInfo(morphName);
+
+            this.engHandler.loopNext(PmdEngHandler.ENGMORPH_LIST);
+        }
+
+        this.engHandler.loopEnd(PmdEngHandler.ENGMORPH_LIST);
+
+        return;
+    }
+
+    /**
+     * PMDモデル英語ボーングループ名のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseEngBoneGroupName()
+            throws IOException, MmdFormatException{
+        int groupNum = getBoneGroupCount();
+
+        if(this.engHandler == null){
+            skip(PmdLimits.MAXBYTES_BONEGROUPNAME * groupNum);
+            return;
+        }
+
+        this.engHandler.loopStart(PmdEngHandler.ENGBONEGROUP_LIST, groupNum);
+
+        for(int ct = 0; ct < groupNum; ct++){
+            String boneGroupName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_BONEGROUPNAME);
+            this.engHandler.pmdEngBoneGroupInfo(boneGroupName);
+
+            this.engHandler.loopNext(PmdEngHandler.ENGBONEGROUP_LIST);
+        }
+
+        this.engHandler.loopEnd(PmdEngHandler.ENGBONEGROUP_LIST);
+
+        return;
+    }
+
+}
index 3088b63..a888d45 100644 (file)
@@ -1,84 +1,84 @@
-/*\r
- * pmd parser extensin 2\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import java.io.IOException;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-\r
-/**\r
- * PMDモデルファイルのパーサ拡張その2。\r
- * ※独自トゥーンテクスチャファイル名対応\r
- */\r
-public class PmdParserExt2 extends PmdParserExt1 {\r
-\r
-    private PmdToonHandler toonHandler = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public PmdParserExt2(MmdSource source){\r
-        super(source);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * トゥーンテクスチャファイルハンドラを登録する。\r
-     * @param handler ハンドラ\r
-     */\r
-    public void setToonHandler(PmdToonHandler handler){\r
-        this.toonHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws MmdFormatException {@inheritDoc}\r
-     */\r
-    @Override\r
-    protected void parseBody()\r
-            throws IOException, MmdFormatException{\r
-        super.parseBody();\r
-\r
-        if(hasMore()){\r
-            parseToonName();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 独自トゥーンテクスチャファイル名のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseToonName() throws IOException, MmdFormatException{\r
-        if(this.toonHandler == null){\r
-            skip(PmdLimits.MAXBYTES_TOONFILENAME * PmdLimits.TOON_FIXEDNUM);\r
-            return;\r
-        }\r
-\r
-        this.toonHandler.loopStart(PmdToonHandler.TOON_LIST,\r
-                                   PmdLimits.TOON_FIXEDNUM );\r
-\r
-        for(int ct = 0; ct < PmdLimits.TOON_FIXEDNUM; ct++){\r
-            String toonName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_TOONFILENAME);\r
-            this.toonHandler.pmdToonFileInfo(toonName);\r
-\r
-            this.toonHandler.loopNext(PmdToonHandler.TOON_LIST);\r
-        }\r
-\r
-        this.toonHandler.loopEnd(PmdToonHandler.TOON_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * pmd parser extensin 2
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import java.io.IOException;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+
+/**
+ * PMDモデルファイルのパーサ拡張その2。
+ * ※独自トゥーンテクスチャファイル名対応
+ */
+public class PmdParserExt2 extends PmdParserExt1 {
+
+    private PmdToonHandler toonHandler = null;
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public PmdParserExt2(MmdSource source){
+        super(source);
+        return;
+    }
+
+    /**
+     * トゥーンテクスチャファイルハンドラを登録する。
+     * @param handler ハンドラ
+     */
+    public void setToonHandler(PmdToonHandler handler){
+        this.toonHandler = handler;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdFormatException {@inheritDoc}
+     */
+    @Override
+    protected void parseBody()
+            throws IOException, MmdFormatException{
+        super.parseBody();
+
+        if(hasMore()){
+            parseToonName();
+        }
+
+        return;
+    }
+
+    /**
+     * 独自トゥーンテクスチャファイル名のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseToonName() throws IOException, MmdFormatException{
+        if(this.toonHandler == null){
+            skip(PmdLimits.MAXBYTES_TOONFILENAME * PmdLimits.TOON_FIXEDNUM);
+            return;
+        }
+
+        this.toonHandler.loopStart(PmdToonHandler.TOON_LIST,
+                                   PmdLimits.TOON_FIXEDNUM );
+
+        for(int ct = 0; ct < PmdLimits.TOON_FIXEDNUM; ct++){
+            String toonName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_TOONFILENAME);
+            this.toonHandler.pmdToonFileInfo(toonName);
+
+            this.toonHandler.loopNext(PmdToonHandler.TOON_LIST);
+        }
+
+        this.toonHandler.loopEnd(PmdToonHandler.TOON_LIST);
+
+        return;
+    }
+
+}
index a34272b..1081901 100644 (file)
-/*\r
- * pmd parser extension 3\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import java.io.IOException;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-\r
-/**\r
- * PMDモデルファイルのパーサ拡張その3。\r
- * ※剛体情報対応\r
- */\r
-public class PmdParserExt3 extends PmdParserExt2 {\r
-\r
-    private static final int RIGID_DATA_SZ = 83;\r
-    private static final int JOINT_DATA_SZ = 124;\r
-\r
-    private PmdRigidHandler rigidHandler = null;\r
-    private PmdJointHandler jointHandler = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source 入力ソース\r
-     */\r
-    public PmdParserExt3(MmdSource source){\r
-        super(source);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体ハンドラを登録する。\r
-     * @param handler 剛体ハンドラ\r
-     */\r
-    public void setRigidHandler(PmdRigidHandler handler){\r
-        this.rigidHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ジョイントハンドラを登録する。\r
-     * @param handler ジョイントハンドラ\r
-     */\r
-    public void setJointHandler(PmdJointHandler handler){\r
-        this.jointHandler = handler;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws MmdFormatException {@inheritDoc}\r
-     */\r
-    @Override\r
-    protected void parseBody()\r
-            throws IOException, MmdFormatException {\r
-        super.parseBody();\r
-\r
-        if(hasMore()){\r
-            parseRigidList();\r
-            parseJointList();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseRigidList() throws IOException, MmdFormatException{\r
-        int rigidNum = parseInteger();\r
-\r
-        if(this.rigidHandler == null){\r
-            skip(RIGID_DATA_SZ * rigidNum);\r
-            return;\r
-        }\r
-\r
-        this.rigidHandler.loopStart(PmdRigidHandler.RIGID_LIST, rigidNum);\r
-\r
-        for(int ct = 0; ct < rigidNum; ct++){\r
-            String rigidName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_RIGIDNAME);\r
-            this.rigidHandler.pmdRigidName(rigidName);\r
-\r
-            int linkedBoneId = parseUShortAsInteger();\r
-            int rigidGroupId = parseUByteAsInteger();\r
-            short collisionMap = parseShort();\r
-            this.rigidHandler.pmdRigidInfo(rigidGroupId, linkedBoneId);\r
-\r
-            byte shapeType = parseByte();\r
-            float width = parseFloat();\r
-            float height = parseFloat();\r
-            float depth = parseFloat();\r
-            this.rigidHandler.pmdRigidShape(shapeType, width, height, depth);\r
-\r
-            float posX = parseFloat();\r
-            float posY = parseFloat();\r
-            float posZ = parseFloat();\r
-            this.rigidHandler.pmdRigidPosition(posX, posY, posZ);\r
-\r
-            float rotX = parseFloat();\r
-            float rotY = parseFloat();\r
-            float rotZ = parseFloat();\r
-            this.rigidHandler.pmdRigidRotation(rotX, rotY, rotZ);\r
-\r
-            float mass = parseFloat();\r
-            float dampingPos = parseFloat();\r
-            float dampingRot = parseFloat();\r
-            float restitution = parseFloat();\r
-            float friction = parseFloat();\r
-            this.rigidHandler.pmdRigidPhysics(mass,\r
-                                              dampingPos, dampingRot,\r
-                                              restitution, friction );\r
-\r
-            byte behaveType = parseByte();\r
-            this.rigidHandler.pmdRigidBehavior(behaveType, collisionMap);\r
-\r
-            this.rigidHandler.loopNext(PmdRigidHandler.RIGID_LIST);\r
-        }\r
-\r
-        this.rigidHandler.loopEnd(PmdRigidHandler.RIGID_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ジョイント情報のパースと通知。\r
-     * @throws IOException IOエラー\r
-     * @throws MmdFormatException フォーマットエラー\r
-     */\r
-    private void parseJointList() throws IOException, MmdFormatException{\r
-        int jointNum = parseInteger();\r
-\r
-        if(this.jointHandler == null){\r
-            skip(JOINT_DATA_SZ * jointNum);\r
-            return;\r
-        }\r
-\r
-        this.jointHandler.loopStart(PmdJointHandler.JOINT_LIST, jointNum);\r
-\r
-        for(int ct = 0; ct < jointNum; ct++){\r
-            String jointName =\r
-                    parseZeroTermString(PmdLimits.MAXBYTES_JOINTNAME);\r
-            this.jointHandler.pmdJointName(jointName);\r
-\r
-            int rigidIdA = parseInteger();\r
-            int rigidIdB = parseInteger();\r
-            this.jointHandler.pmdJointLink(rigidIdA, rigidIdB);\r
-\r
-            float posX = parseFloat();\r
-            float posY = parseFloat();\r
-            float posZ = parseFloat();\r
-            this.jointHandler.pmdJointPosition(posX, posY, posZ);\r
-\r
-            float rotX = parseFloat();\r
-            float rotY = parseFloat();\r
-            float rotZ = parseFloat();\r
-            this.jointHandler.pmdJointRotation(rotX, rotY, rotZ);\r
-\r
-            float posXlim1 = parseFloat();\r
-            float posYlim1 = parseFloat();\r
-            float posZlim1 = parseFloat();\r
-            float posXlim2 = parseFloat();\r
-            float posYlim2 = parseFloat();\r
-            float posZlim2 = parseFloat();\r
-            this.jointHandler.pmdPositionLimit(posXlim1, posXlim2,\r
-                                               posYlim1, posYlim2,\r
-                                               posZlim1, posZlim2 );\r
-\r
-            float rotXlim1 = parseFloat();\r
-            float rotYlim1 = parseFloat();\r
-            float rotZlim1 = parseFloat();\r
-            float rotXlim2 = parseFloat();\r
-            float rotYlim2 = parseFloat();\r
-            float rotZlim2 = parseFloat();\r
-            this.jointHandler.pmdRotationLimit(rotXlim1, rotXlim2,\r
-                                               rotYlim1, rotYlim2,\r
-                                               rotZlim1, rotZlim2 );\r
-\r
-            float elasticPosX = parseFloat();\r
-            float elasticPosY = parseFloat();\r
-            float elasticPosZ = parseFloat();\r
-            this.jointHandler.pmdElasticPosition(elasticPosX,\r
-                                                 elasticPosY,\r
-                                                 elasticPosZ );\r
-\r
-            float elasticRotX = parseFloat();\r
-            float elasticRotY = parseFloat();\r
-            float elasticRotZ = parseFloat();\r
-            this.jointHandler.pmdElasticRotation(elasticRotX,\r
-                                                 elasticRotY,\r
-                                                 elasticRotZ );\r
-\r
-            this.jointHandler.loopNext(PmdJointHandler.JOINT_LIST);\r
-        }\r
-\r
-        this.jointHandler.loopEnd(PmdJointHandler.JOINT_LIST);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * pmd parser extension 3
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import java.io.IOException;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+
+/**
+ * PMDモデルファイルのパーサ拡張その3。
+ * ※剛体情報対応
+ */
+public class PmdParserExt3 extends PmdParserExt2 {
+
+    private static final int RIGID_DATA_SZ = 83;
+    private static final int JOINT_DATA_SZ = 124;
+
+    private PmdRigidHandler rigidHandler = null;
+    private PmdJointHandler jointHandler = null;
+
+    /**
+     * コンストラクタ。
+     * @param source 入力ソース
+     */
+    public PmdParserExt3(MmdSource source){
+        super(source);
+        return;
+    }
+
+    /**
+     * 剛体ハンドラを登録する。
+     * @param handler 剛体ハンドラ
+     */
+    public void setRigidHandler(PmdRigidHandler handler){
+        this.rigidHandler = handler;
+        return;
+    }
+
+    /**
+     * ジョイントハンドラを登録する。
+     * @param handler ジョイントハンドラ
+     */
+    public void setJointHandler(PmdJointHandler handler){
+        this.jointHandler = handler;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdFormatException {@inheritDoc}
+     */
+    @Override
+    protected void parseBody()
+            throws IOException, MmdFormatException {
+        super.parseBody();
+
+        if(hasMore()){
+            parseRigidList();
+            parseJointList();
+        }
+
+        return;
+    }
+
+    /**
+     * 剛体情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseRigidList() throws IOException, MmdFormatException{
+        int rigidNum = parseInteger();
+
+        if(this.rigidHandler == null){
+            skip(RIGID_DATA_SZ * rigidNum);
+            return;
+        }
+
+        this.rigidHandler.loopStart(PmdRigidHandler.RIGID_LIST, rigidNum);
+
+        for(int ct = 0; ct < rigidNum; ct++){
+            String rigidName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_RIGIDNAME);
+            this.rigidHandler.pmdRigidName(rigidName);
+
+            int linkedBoneId = parseUShortAsInteger();
+            int rigidGroupId = parseUByteAsInteger();
+            short collisionMap = parseShort();
+            this.rigidHandler.pmdRigidInfo(rigidGroupId, linkedBoneId);
+
+            byte shapeType = parseByte();
+            float width = parseFloat();
+            float height = parseFloat();
+            float depth = parseFloat();
+            this.rigidHandler.pmdRigidShape(shapeType, width, height, depth);
+
+            float posX = parseFloat();
+            float posY = parseFloat();
+            float posZ = parseFloat();
+            this.rigidHandler.pmdRigidPosition(posX, posY, posZ);
+
+            float rotX = parseFloat();
+            float rotY = parseFloat();
+            float rotZ = parseFloat();
+            this.rigidHandler.pmdRigidRotation(rotX, rotY, rotZ);
+
+            float mass = parseFloat();
+            float dampingPos = parseFloat();
+            float dampingRot = parseFloat();
+            float restitution = parseFloat();
+            float friction = parseFloat();
+            this.rigidHandler.pmdRigidPhysics(mass,
+                                              dampingPos, dampingRot,
+                                              restitution, friction );
+
+            byte behaveType = parseByte();
+            this.rigidHandler.pmdRigidBehavior(behaveType, collisionMap);
+
+            this.rigidHandler.loopNext(PmdRigidHandler.RIGID_LIST);
+        }
+
+        this.rigidHandler.loopEnd(PmdRigidHandler.RIGID_LIST);
+
+        return;
+    }
+
+    /**
+     * ジョイント情報のパースと通知。
+     * @throws IOException IOエラー
+     * @throws MmdFormatException フォーマットエラー
+     */
+    private void parseJointList() throws IOException, MmdFormatException{
+        int jointNum = parseInteger();
+
+        if(this.jointHandler == null){
+            skip(JOINT_DATA_SZ * jointNum);
+            return;
+        }
+
+        this.jointHandler.loopStart(PmdJointHandler.JOINT_LIST, jointNum);
+
+        for(int ct = 0; ct < jointNum; ct++){
+            String jointName =
+                    parseZeroTermString(PmdLimits.MAXBYTES_JOINTNAME);
+            this.jointHandler.pmdJointName(jointName);
+
+            int rigidIdA = parseInteger();
+            int rigidIdB = parseInteger();
+            this.jointHandler.pmdJointLink(rigidIdA, rigidIdB);
+
+            float posX = parseFloat();
+            float posY = parseFloat();
+            float posZ = parseFloat();
+            this.jointHandler.pmdJointPosition(posX, posY, posZ);
+
+            float rotX = parseFloat();
+            float rotY = parseFloat();
+            float rotZ = parseFloat();
+            this.jointHandler.pmdJointRotation(rotX, rotY, rotZ);
+
+            float posXlim1 = parseFloat();
+            float posYlim1 = parseFloat();
+            float posZlim1 = parseFloat();
+            float posXlim2 = parseFloat();
+            float posYlim2 = parseFloat();
+            float posZlim2 = parseFloat();
+            this.jointHandler.pmdPositionLimit(posXlim1, posXlim2,
+                                               posYlim1, posYlim2,
+                                               posZlim1, posZlim2 );
+
+            float rotXlim1 = parseFloat();
+            float rotYlim1 = parseFloat();
+            float rotZlim1 = parseFloat();
+            float rotXlim2 = parseFloat();
+            float rotYlim2 = parseFloat();
+            float rotZlim2 = parseFloat();
+            this.jointHandler.pmdRotationLimit(rotXlim1, rotXlim2,
+                                               rotYlim1, rotYlim2,
+                                               rotZlim1, rotZlim2 );
+
+            float elasticPosX = parseFloat();
+            float elasticPosY = parseFloat();
+            float elasticPosZ = parseFloat();
+            this.jointHandler.pmdElasticPosition(elasticPosX,
+                                                 elasticPosY,
+                                                 elasticPosZ );
+
+            float elasticRotX = parseFloat();
+            float elasticRotY = parseFloat();
+            float elasticRotZ = parseFloat();
+            this.jointHandler.pmdElasticRotation(elasticRotX,
+                                                 elasticRotY,
+                                                 elasticRotZ );
+
+            this.jointHandler.loopNext(PmdJointHandler.JOINT_LIST);
+        }
+
+        this.jointHandler.loopEnd(PmdJointHandler.JOINT_LIST);
+
+        return;
+    }
+
+}
index 98ee70c..8cb641f 100644 (file)
-/*\r
- * PMD rigid information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの各種剛体情報の通知用ハンドラ。\r
- */\r
-public interface PmdRigidHandler extends LoopHandler {\r
-\r
-    /**\r
-     * 剛体情報パースステージ。\r
-     */\r
-    class PmdRigidStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdRigidStage(){ super(); return; }\r
-    }\r
-\r
-    /** 剛体情報抽出ループ。 */\r
-    PmdRigidStage RIGID_LIST = new PmdRigidStage();\r
-\r
-    /**\r
-     * 剛体名の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param rigidName 剛体名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidName(String rigidName)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体基本情報の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param rigidGroupId 剛体グループ番号から1引いた数。(0-15)\r
-     * @param linkedBoneId 接続先ボーンID\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidInfo(int rigidGroupId,\r
-                        int linkedBoneId)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体形状の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param shapeType 形状種別。\r
-     * <ul>\r
-     * <li>0x00:球\r
-     * <li>0x01:箱\r
-     * <li>0x02:カプセル\r
-     * </ul>\r
-     * @param width 球orカプセル半径。箱の幅。\r
-     * @param height 箱orカプセルの高さ\r
-     * @param depth 箱の奥行き\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidShape(byte shapeType,\r
-                         float width, float height, float depth)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体位置の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param posX X座標\r
-     * @param posY Y座標\r
-     * @param posZ Z座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidPosition(float posX, float posY, float posZ)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体姿勢の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param radX X軸回転量(radian)\r
-     * @param radY Y軸回転量(radian)\r
-     * @param radZ Z軸回転量(radian)\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidRotation(float radX, float radY, float radZ)\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体物理系数の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param mass 質量\r
-     * @param dampingPos 移動減衰率\r
-     * @param dampingRot 回転減衰率\r
-     * @param restitution 反発力\r
-     * @param friction 摩擦力\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidPhysics(float mass,\r
-                           float dampingPos, float dampingRot,\r
-                           float restitution, float friction )\r
-        throws MmdFormatException;\r
-\r
-    /**\r
-     * 剛体の振る舞い情報の通知を受け取る。\r
-     * {@link #RIGID_LIST}ループの構成要素。\r
-     * @param behaveType 剛体タイプ。\r
-     * <ul>\r
-     * <li>0:ボーン追従\r
-     * <li>1:物理演算\r
-     * <li>2:物理演算+ボーン位置合わせ\r
-     * </ul>\r
-     * @param collisionMap 非衝突剛体グループビットマップ。\r
-     * (衝突グループ番号-1)位置のビット位置は1に、\r
-     * (非衝突グループ番号-1)位置のビット位置は0になる。\r
-     * 例)グループ1と8のみが非衝突指定の場合、0xff7eになる。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdRigidBehavior(byte behaveType, short collisionMap)\r
-        throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD rigid information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの各種剛体情報の通知用ハンドラ。
+ */
+public interface PmdRigidHandler extends LoopHandler {
+
+    /**
+     * 剛体情報パースステージ。
+     */
+    class PmdRigidStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdRigidStage(){ super(); return; }
+    }
+
+    /** 剛体情報抽出ループ。 */
+    PmdRigidStage RIGID_LIST = new PmdRigidStage();
+
+    /**
+     * 剛体名の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param rigidName 剛体名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidName(String rigidName)
+        throws MmdFormatException;
+
+    /**
+     * 剛体基本情報の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param rigidGroupId 剛体グループ番号から1引いた数。(0-15)
+     * @param linkedBoneId 接続先ボーンID
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidInfo(int rigidGroupId,
+                        int linkedBoneId)
+        throws MmdFormatException;
+
+    /**
+     * 剛体形状の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param shapeType 形状種別。
+     * <ul>
+     * <li>0x00:球
+     * <li>0x01:箱
+     * <li>0x02:カプセル
+     * </ul>
+     * @param width 球orカプセル半径。箱の幅。
+     * @param height 箱orカプセルの高さ
+     * @param depth 箱の奥行き
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidShape(byte shapeType,
+                         float width, float height, float depth)
+        throws MmdFormatException;
+
+    /**
+     * 剛体位置の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param posX X座標
+     * @param posY Y座標
+     * @param posZ Z座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidPosition(float posX, float posY, float posZ)
+        throws MmdFormatException;
+
+    /**
+     * 剛体姿勢の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param radX X軸回転量(radian)
+     * @param radY Y軸回転量(radian)
+     * @param radZ Z軸回転量(radian)
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidRotation(float radX, float radY, float radZ)
+        throws MmdFormatException;
+
+    /**
+     * 剛体物理系数の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param mass 質量
+     * @param dampingPos 移動減衰率
+     * @param dampingRot 回転減衰率
+     * @param restitution 反発力
+     * @param friction 摩擦力
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidPhysics(float mass,
+                           float dampingPos, float dampingRot,
+                           float restitution, float friction )
+        throws MmdFormatException;
+
+    /**
+     * 剛体の振る舞い情報の通知を受け取る。
+     * {@link #RIGID_LIST}ループの構成要素。
+     * @param behaveType 剛体タイプ。
+     * <ul>
+     * <li>0:ボーン追従
+     * <li>1:物理演算
+     * <li>2:物理演算+ボーン位置合わせ
+     * </ul>
+     * @param collisionMap 非衝突剛体グループビットマップ。
+     * (衝突グループ番号-1)位置のビット位置は1に、
+     * (非衝突グループ番号-1)位置のビット位置は0になる。
+     * 例)グループ1と8のみが非衝突指定の場合、0xff7eになる。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdRigidBehavior(byte behaveType, short collisionMap)
+        throws MmdFormatException;
+
+}
index 9d4f591..16f80f9 100644 (file)
-/*\r
- * PMD shape information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの各種形状(頂点、面)の通知用ハンドラ。\r
- * 0から始まる頂点ID順に頂点は出現する。\r
- * 0から始まる面ID順に面は出現する。\r
- */\r
-public interface PmdShapeHandler extends LoopHandler {\r
-\r
-    /**\r
-     * モデル形状パースステージ。\r
-     */\r
-    class PmdShapeStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdShapeStage(){ super(); return; }\r
-    }\r
-\r
-    /** 頂点抽出ループ。 */\r
-    PmdShapeStage VERTEX_LIST = new PmdShapeStage();\r
-    /** 面抽出ループ。 */\r
-    PmdShapeStage SURFACE_LIST = new PmdShapeStage();\r
-\r
-    /**\r
-     * 頂点の座標の通知を受け取る。\r
-     * {@link #VERTEX_LIST}ループの構成要素\r
-     * @param xPos X座標\r
-     * @param yPos Y座標\r
-     * @param zPos Z座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdVertexPosition(float xPos, float yPos, float zPos)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 頂点の法線情報の通知を受け取る。\r
-     * {@link #VERTEX_LIST}ループの構成要素\r
-     * ※単位ベクトル化必須?\r
-     * @param xVec 法線ベクトルX成分\r
-     * @param yVec 法線ベクトルY成分\r
-     * @param zVec 法線ベクトルZ成分\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdVertexNormal(float xVec, float yVec, float zVec)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 頂点のUVマッピング情報の通知を受け取る。\r
-     * (頂点UV)\r
-     * {@link #VERTEX_LIST}ループの構成要素\r
-     * @param uVal テクスチャのU座標\r
-     * @param vVal テクスチャのV座標\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdVertexUV(float uVal, float vVal )\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 頂点のボーン間ウェイトバランス情報の通知を受け取る。\r
-     * {@link #VERTEX_LIST}ループの構成要素\r
-     * @param boneId1 ボーンその1識別ID\r
-     * @param boneId2 ボーンその2識別ID\r
-     * @param weightForB1 ボーンその1への影響度。0(min)~100(max)\r
-     * ボーンその2への影響度は100からの引き算で求める。\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdVertexWeight(int boneId1, int boneId2, int weightForB1)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 頂点のエッジ表現情報の通知を受け取る。\r
-     * 材質単位でのエッジ表現指定に優先される。\r
-     * {@link #VERTEX_LIST}ループの構成要素\r
-     * @param hideEdge エッジ無効ならtrue\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdVertexEdge(boolean hideEdge)\r
-            throws MmdFormatException;\r
-\r
-    /**\r
-     * 3つの頂点から構成される面情報の通知を受け取る。\r
-     * {@link #SURFACE_LIST}ループの構成要素\r
-     * @param vertexId1 頂点IDその1\r
-     * @param vertexId2 頂点IDその1\r
-     * @param vertexId3 頂点IDその1\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdSurfaceTriangle(int vertexId1, int vertexId2, int vertexId3)\r
-            throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD shape information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの各種形状(頂点、面)の通知用ハンドラ。
+ * 0から始まる頂点ID順に頂点は出現する。
+ * 0から始まる面ID順に面は出現する。
+ */
+public interface PmdShapeHandler extends LoopHandler {
+
+    /**
+     * モデル形状パースステージ。
+     */
+    class PmdShapeStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdShapeStage(){ super(); return; }
+    }
+
+    /** 頂点抽出ループ。 */
+    PmdShapeStage VERTEX_LIST = new PmdShapeStage();
+    /** 面抽出ループ。 */
+    PmdShapeStage SURFACE_LIST = new PmdShapeStage();
+
+    /**
+     * 頂点の座標の通知を受け取る。
+     * {@link #VERTEX_LIST}ループの構成要素
+     * @param xPos X座標
+     * @param yPos Y座標
+     * @param zPos Z座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdVertexPosition(float xPos, float yPos, float zPos)
+            throws MmdFormatException;
+
+    /**
+     * 頂点の法線情報の通知を受け取る。
+     * {@link #VERTEX_LIST}ループの構成要素
+     * ※単位ベクトル化必須?
+     * @param xVec 法線ベクトルX成分
+     * @param yVec 法線ベクトルY成分
+     * @param zVec 法線ベクトルZ成分
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdVertexNormal(float xVec, float yVec, float zVec)
+            throws MmdFormatException;
+
+    /**
+     * 頂点のUVマッピング情報の通知を受け取る。
+     * (頂点UV)
+     * {@link #VERTEX_LIST}ループの構成要素
+     * @param uVal テクスチャのU座標
+     * @param vVal テクスチャのV座標
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdVertexUV(float uVal, float vVal )
+            throws MmdFormatException;
+
+    /**
+     * 頂点のボーン間ウェイトバランス情報の通知を受け取る。
+     * {@link #VERTEX_LIST}ループの構成要素
+     * @param boneId1 ボーンその1識別ID
+     * @param boneId2 ボーンその2識別ID
+     * @param weightForB1 ボーンその1への影響度。0(min)~100(max)
+     * ボーンその2への影響度は100からの引き算で求める。
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdVertexWeight(int boneId1, int boneId2, int weightForB1)
+            throws MmdFormatException;
+
+    /**
+     * 頂点のエッジ表現情報の通知を受け取る。
+     * 材質単位でのエッジ表現指定に優先される。
+     * {@link #VERTEX_LIST}ループの構成要素
+     * @param hideEdge エッジ無効ならtrue
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdVertexEdge(boolean hideEdge)
+            throws MmdFormatException;
+
+    /**
+     * 3つの頂点から構成される面情報の通知を受け取る。
+     * {@link #SURFACE_LIST}ループの構成要素
+     * @param vertexId1 頂点IDその1
+     * @param vertexId2 頂点IDその1
+     * @param vertexId3 頂点IDその1
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdSurfaceTriangle(int vertexId1, int vertexId2, int vertexId3)
+            throws MmdFormatException;
+
+}
index 8d285f8..ded567a 100644 (file)
@@ -1,39 +1,39 @@
-/*\r
- * PMD toon texture file information handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.LoopHandler;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-\r
-/**\r
- * PMDモデルの独自トゥーンテクスチャファイル名の通知用ハンドラ。\r
- */\r
-public interface PmdToonHandler extends LoopHandler {\r
-\r
-    /**\r
-     * 独自トゥーンテクスチャファイル名パースステージ。\r
-     */\r
-    class PmdToonStage extends ParseStage{\r
-        /** コンストラクタ。 */\r
-        PmdToonStage(){ super(); return; }\r
-    }\r
-\r
-    /** トゥーンテクスチャファイル名抽出ループ。 */\r
-    PmdToonStage TOON_LIST = new PmdToonStage();\r
-\r
-    /**\r
-     * 独自トゥーンテクスチャファイル名の通知を受け取る。\r
-     * {@link #TOON_LIST}ループの構成要素\r
-     * @param toonName 独自トゥーンテクスチャファイル名\r
-     * @throws MmdFormatException 不正フォーマットによる\r
-     * パース処理の中断をパーサに指示\r
-     */\r
-    void pmdToonFileInfo(String toonName) throws MmdFormatException;\r
-\r
-}\r
+/*
+ * PMD toon texture file information handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+import jp.sourceforge.mikutoga.parser.LoopHandler;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+
+/**
+ * PMDモデルの独自トゥーンテクスチャファイル名の通知用ハンドラ。
+ */
+public interface PmdToonHandler extends LoopHandler {
+
+    /**
+     * 独自トゥーンテクスチャファイル名パースステージ。
+     */
+    class PmdToonStage extends ParseStage{
+        /** コンストラクタ。 */
+        PmdToonStage(){ super(); return; }
+    }
+
+    /** トゥーンテクスチャファイル名抽出ループ。 */
+    PmdToonStage TOON_LIST = new PmdToonStage();
+
+    /**
+     * 独自トゥーンテクスチャファイル名の通知を受け取る。
+     * {@link #TOON_LIST}ループの構成要素
+     * @param toonName 独自トゥーンテクスチャファイル名
+     * @throws MmdFormatException 不正フォーマットによる
+     * パース処理の中断をパーサに指示
+     */
+    void pmdToonFileInfo(String toonName) throws MmdFormatException;
+
+}
index cf9ed5d..0b08cc3 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * PMDモデルファイル用パーサライブラリ。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser.pmd;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * PMDモデルファイル用パーサライブラリ。
+ */
+
+package jp.sourceforge.mikutoga.parser.pmd;
+
+/* EOF */
index e62ab54..8fb3520 100644 (file)
-/*\r
- * bone group\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * ボーングループ。\r
- * ボーングループ名と0個以上のボーンを配下に持つ。\r
- * 通し番号0のボーングループは、暗黙に用意される「デフォルトボーングループ」とする。\r
- */\r
-public class BoneGroup implements SerialNumbered , Iterable<BoneInfo> {\r
-\r
-    private final I18nText groupName = new I18nText();\r
-\r
-    private final List<BoneInfo> boneList = new ArrayList<BoneInfo>();\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public BoneGroup(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーングループ名を返す。\r
-     * @return ボーングループ名\r
-     */\r
-    public I18nText getGroupName(){\r
-        return this.groupName;\r
-    }\r
-\r
-    /**\r
-     * ボーンリストを取得する。\r
-     * @return ボーンリスト\r
-     */\r
-    public List<BoneInfo> getBoneList(){\r
-        return this.boneList;\r
-    }\r
-\r
-    /**\r
-     * デフォルトボーングループか否か判定する。\r
-     * 通し番号が0ならデフォルトボーングループ。\r
-     * @return デフォルトボーングループならtrue\r
-     */\r
-    public boolean isDefaultBoneGroup(){\r
-        if(this.serialNo == 0) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<BoneInfo> iterator(){\r
-        return this.boneList.iterator();\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * ボーングループ番号(ボーン枠番号)を返す。\r
-     * 常に通し番号より1少ない値となる。\r
-     * デフォルトボーングループは-1となる。\r
-     * @return ボーングループ番号\r
-     */\r
-    public int getBoneGroupNumber(){\r
-        return this.serialNo - 1;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("BoneGroup(")\r
-              .append(this.groupName)\r
-              .append(") [");\r
-\r
-        boolean dumped = false;\r
-        for(BoneInfo bone : this){\r
-            if(dumped) result.append(", ");\r
-            result.append(bone.getBoneName());\r
-            dumped = true;\r
-        }\r
-\r
-        result.append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * bone group
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * ボーングループ。
+ * ボーングループ名と0個以上のボーンを配下に持つ。
+ * 通し番号0のボーングループは、暗黙に用意される「デフォルトボーングループ」とする。
+ */
+public class BoneGroup implements SerialNumbered , Iterable<BoneInfo> {
+
+    private final I18nText groupName = new I18nText();
+
+    private final List<BoneInfo> boneList = new ArrayList<BoneInfo>();
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public BoneGroup(){
+        super();
+        return;
+    }
+
+    /**
+     * ボーングループ名を返す。
+     * @return ボーングループ名
+     */
+    public I18nText getGroupName(){
+        return this.groupName;
+    }
+
+    /**
+     * ボーンリストを取得する。
+     * @return ボーンリスト
+     */
+    public List<BoneInfo> getBoneList(){
+        return this.boneList;
+    }
+
+    /**
+     * デフォルトボーングループか否か判定する。
+     * 通し番号が0ならデフォルトボーングループ。
+     * @return デフォルトボーングループならtrue
+     */
+    public boolean isDefaultBoneGroup(){
+        if(this.serialNo == 0) return true;
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<BoneInfo> iterator(){
+        return this.boneList.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * ボーングループ番号(ボーン枠番号)を返す。
+     * 常に通し番号より1少ない値となる。
+     * デフォルトボーングループは-1となる。
+     * @return ボーングループ番号
+     */
+    public int getBoneGroupNumber(){
+        return this.serialNo - 1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("BoneGroup(")
+              .append(this.groupName)
+              .append(") [");
+
+        boolean dumped = false;
+        for(BoneInfo bone : this){
+            if(dumped) result.append(", ");
+            result.append(bone.getBoneName());
+            dumped = true;
+        }
+
+        result.append(']');
+
+        return result.toString();
+    }
+
+}
index d19efc4..e8f2882 100644 (file)
-/*\r
- * bone information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * ボーン情報。\r
- */\r
-public class BoneInfo implements SerialNumbered {\r
-\r
-    private final I18nText boneName = new I18nText();\r
-    private BoneType boneType;\r
-\r
-    private BoneInfo prevBone;\r
-    private BoneInfo nextBone;\r
-    private BoneInfo ikBone;\r
-\r
-    private final Pos3d position = new Pos3d();\r
-\r
-    private int rotationRatio;\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public BoneInfo(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーン名を返す。\r
-     * @return ボーン名\r
-     */\r
-    public I18nText getBoneName(){\r
-        return this.boneName;\r
-    }\r
-\r
-    /**\r
-     * ボーン種別を設定する。\r
-     * @param type ボーン種別\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setBoneType(BoneType type) throws NullPointerException{\r
-        if(type == null) throw new NullPointerException();\r
-        this.boneType = type;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーン種別を返す。\r
-     * @return ボーン種別\r
-     */\r
-    public BoneType getBoneType(){\r
-        return this.boneType;\r
-    }\r
-\r
-    /**\r
-     * 親(前)ボーンを設定する。\r
-     * @param prevBone 前ボーン。ない場合はnullを指定。\r
-     */\r
-    public void setPrevBone(BoneInfo prevBone){\r
-        this.prevBone = prevBone;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 親(前)ボーンを返す。\r
-     * @return 前ボーン。ない場合はnullを返す。\r
-     */\r
-    public BoneInfo getPrevBone(){\r
-        return this.prevBone;\r
-    }\r
-\r
-    /**\r
-     * 子(次)ボーンを設定する。\r
-     * 捩りボーンでは軸方向に位置するボーン、\r
-     * 回転連動ボーンでは影響元ボーン。\r
-     * @param nextBone 次ボーン。ない場合はnullを指定。\r
-     */\r
-    public void setNextBone(BoneInfo nextBone){\r
-        this.nextBone = nextBone;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 子(次)ボーンを返す。\r
-     * 捩りボーンでは軸方向に位置するボーン、\r
-     * 回転連動ボーンでは影響元ボーン。\r
-     * @return 次ボーン。ない場合はnullを返す。\r
-     */\r
-    public BoneInfo getNextBone(){\r
-        return this.nextBone;\r
-    }\r
-\r
-    /**\r
-     * このボーンが影響を受けるIKボーンを設定する。\r
-     * @param ikBoneArg IKボーン。ない場合はnullを指定。\r
-     */\r
-    public void setIKBone(BoneInfo ikBoneArg){\r
-        this.ikBone = ikBoneArg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * このボーンが影響を受けるIKボーンを返す。\r
-     * @return IKボーン。ない場合はnull\r
-     */\r
-    public BoneInfo getIKBone(){\r
-        return this.ikBone;\r
-    }\r
-\r
-    /**\r
-     * ボーン位置を返す。\r
-     * @return ボーン位置\r
-     */\r
-    public Pos3d getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * 回転連動の影響度を返す。\r
-     * 回転連動ボーンの場合のみ有効。\r
-     * @return 回転連動の影響度\r
-     */\r
-    public int getRotationRatio(){\r
-        return this.rotationRatio;\r
-    }\r
-\r
-    /**\r
-     * 回転連動の影響度を設定する。\r
-     * 回転連動ボーンの場合のみ有効。\r
-     * @param ratio 回転連動の影響度\r
-     */\r
-    public void setRotationRatio(int ratio){\r
-        this.rotationRatio = ratio;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Bone")\r
-              .append(this.serialNo)\r
-              .append("(")\r
-              .append(this.boneName.getPrimaryText())\r
-              .append(")");\r
-\r
-        result.append(" type=")\r
-              .append(this.boneType);\r
-\r
-        result.append(" prev=");\r
-        if(this.prevBone != null) result.append(this.prevBone.getBoneName());\r
-        else                      result.append("NONE");\r
-\r
-        result.append(" next=");\r
-        if(this.nextBone != null) result.append(this.nextBone.getBoneName());\r
-        else                      result.append("NONE");\r
-\r
-        if(this.boneType == BoneType.LINKEDROT){\r
-            result.append(" rotraio=").append(this.rotationRatio);\r
-        }else{\r
-            result.append(" ik=");\r
-            if(this.ikBone != null) result.append(this.ikBone.getBoneName());\r
-            else                    result.append("NONE");\r
-        }\r
-\r
-        result.append(" ").append(this.position);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * bone information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * ボーン情報。
+ */
+public class BoneInfo implements SerialNumbered {
+
+    private final I18nText boneName = new I18nText();
+    private BoneType boneType;
+
+    private BoneInfo prevBone;
+    private BoneInfo nextBone;
+    private BoneInfo ikBone;
+
+    private final Pos3d position = new Pos3d();
+
+    private int rotationRatio;
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public BoneInfo(){
+        super();
+        return;
+    }
+
+    /**
+     * ボーン名を返す。
+     * @return ボーン名
+     */
+    public I18nText getBoneName(){
+        return this.boneName;
+    }
+
+    /**
+     * ボーン種別を設定する。
+     * @param type ボーン種別
+     * @throws NullPointerException 引数がnull
+     */
+    public void setBoneType(BoneType type) throws NullPointerException{
+        if(type == null) throw new NullPointerException();
+        this.boneType = type;
+        return;
+    }
+
+    /**
+     * ボーン種別を返す。
+     * @return ボーン種別
+     */
+    public BoneType getBoneType(){
+        return this.boneType;
+    }
+
+    /**
+     * 親(前)ボーンを設定する。
+     * @param prevBone 前ボーン。ない場合はnullを指定。
+     */
+    public void setPrevBone(BoneInfo prevBone){
+        this.prevBone = prevBone;
+        return;
+    }
+
+    /**
+     * 親(前)ボーンを返す。
+     * @return 前ボーン。ない場合はnullを返す。
+     */
+    public BoneInfo getPrevBone(){
+        return this.prevBone;
+    }
+
+    /**
+     * 子(次)ボーンを設定する。
+     * 捩りボーンでは軸方向に位置するボーン、
+     * 回転連動ボーンでは影響元ボーン。
+     * @param nextBone 次ボーン。ない場合はnullを指定。
+     */
+    public void setNextBone(BoneInfo nextBone){
+        this.nextBone = nextBone;
+        return;
+    }
+
+    /**
+     * 子(次)ボーンを返す。
+     * 捩りボーンでは軸方向に位置するボーン、
+     * 回転連動ボーンでは影響元ボーン。
+     * @return 次ボーン。ない場合はnullを返す。
+     */
+    public BoneInfo getNextBone(){
+        return this.nextBone;
+    }
+
+    /**
+     * このボーンが影響を受けるIKボーンを設定する。
+     * @param ikBoneArg IKボーン。ない場合はnullを指定。
+     */
+    public void setIKBone(BoneInfo ikBoneArg){
+        this.ikBone = ikBoneArg;
+        return;
+    }
+
+    /**
+     * このボーンが影響を受けるIKボーンを返す。
+     * @return IKボーン。ない場合はnull
+     */
+    public BoneInfo getIKBone(){
+        return this.ikBone;
+    }
+
+    /**
+     * ボーン位置を返す。
+     * @return ボーン位置
+     */
+    public Pos3d getPosition(){
+        return this.position;
+    }
+
+    /**
+     * 回転連動の影響度を返す。
+     * 回転連動ボーンの場合のみ有効。
+     * @return 回転連動の影響度
+     */
+    public int getRotationRatio(){
+        return this.rotationRatio;
+    }
+
+    /**
+     * 回転連動の影響度を設定する。
+     * 回転連動ボーンの場合のみ有効。
+     * @param ratio 回転連動の影響度
+     */
+    public void setRotationRatio(int ratio){
+        this.rotationRatio = ratio;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Bone")
+              .append(this.serialNo)
+              .append("(")
+              .append(this.boneName.getPrimaryText())
+              .append(")");
+
+        result.append(" type=")
+              .append(this.boneType);
+
+        result.append(" prev=");
+        if(this.prevBone != null) result.append(this.prevBone.getBoneName());
+        else                      result.append("NONE");
+
+        result.append(" next=");
+        if(this.nextBone != null) result.append(this.nextBone.getBoneName());
+        else                      result.append("NONE");
+
+        if(this.boneType == BoneType.LINKEDROT){
+            result.append(" rotraio=").append(this.rotationRatio);
+        }else{
+            result.append(" ik=");
+            if(this.ikBone != null) result.append(this.ikBone.getBoneName());
+            else                    result.append("NONE");
+        }
+
+        result.append(" ").append(this.position);
+
+        return result.toString();
+    }
+
+}
index 365b020..8a916a4 100644 (file)
-/*\r
- * bone type\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Locale;\r
-import java.util.ResourceBundle;\r
-\r
-/**\r
- * ボーン種別。\r
- * <ul>\r
- * <li>0x00:回転\r
- * <li>0x01:回転/移動\r
- * <li>0x02:IK\r
- * <li>0x03:不明\r
- * <li>0x04:IK影響下(回転)\r
- * <li>0x05:回転影響下\r
- * <li>0x06:IK接続先\r
- * <li>0x07:非表示\r
- * <li>0x08:捩り\r
- * <li>0x09:回転連動\r
- * </ul>\r
- */\r
-public enum BoneType {\r
-\r
-    /** 回転。 */\r
-    ROTATE(0x00),\r
-    /** 回転/移動。 */\r
-    ROTMOV(0x01),\r
-    /** IK。 */\r
-    IK(0x02),\r
-    /** 不明。 */\r
-    UNKNOWN(0x03),\r
-    /** IK影響下(回転)。 */\r
-    UNDERIK(0x04),\r
-    /** 回転影響下。 */\r
-    UNDERROT(0x05),\r
-    /** IK接続先。 */\r
-    IKCONNECTED(0x06),\r
-    /** 非表示。 */\r
-    HIDDEN(0x07),\r
-    /** 捩り。 */\r
-    TWIST(0x08),\r
-    /** 回転連動。 */\r
-    LINKEDROT(0x09),\r
-    ;\r
-\r
-    private static final String FAMILY_NAME =\r
-            "jp.sourceforge.mikutoga.pmd.resources.BoneTypeName";\r
-\r
-    private final byte encoded;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化int値\r
-     */\r
-    private BoneType(int code){\r
-        this((byte)code);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化byte値\r
-     */\r
-    private BoneType(byte code){\r
-        this.encoded = code;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値からデコードする。\r
-     * @param code byte値\r
-     * @return デコードされた列挙子。該当するものがなければnull\r
-     */\r
-    public static BoneType decode(byte code){\r
-        BoneType result = null;\r
-\r
-        for(BoneType type : values()){\r
-            if(type.encode() == code){\r
-                result = type;\r
-                break;\r
-            }\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * byte値にエンコードする。\r
-     * @return byte値\r
-     */\r
-    public byte encode(){\r
-        return this.encoded;\r
-    }\r
-\r
-    /**\r
-     * デフォルトロケールでの表示名を返す。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(){\r
-        Locale locale = Locale.getDefault();\r
-        return getGuiName(locale);\r
-    }\r
-\r
-    /**\r
-     * ロケールに準じた表示名を返す。\r
-     * @param locale ロケール。nullならデフォルトロケールと解釈される。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(Locale locale){\r
-        if(locale == null) return getGuiName();\r
-        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);\r
-        String key = name();\r
-        String result = rb.getString(key);\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * bone type
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * ボーン種別。
+ * <ul>
+ * <li>0x00:回転
+ * <li>0x01:回転/移動
+ * <li>0x02:IK
+ * <li>0x03:不明
+ * <li>0x04:IK影響下(回転)
+ * <li>0x05:回転影響下
+ * <li>0x06:IK接続先
+ * <li>0x07:非表示
+ * <li>0x08:捩り
+ * <li>0x09:回転連動
+ * </ul>
+ */
+public enum BoneType {
+
+    /** 回転。 */
+    ROTATE(0x00),
+    /** 回転/移動。 */
+    ROTMOV(0x01),
+    /** IK。 */
+    IK(0x02),
+    /** 不明。 */
+    UNKNOWN(0x03),
+    /** IK影響下(回転)。 */
+    UNDERIK(0x04),
+    /** 回転影響下。 */
+    UNDERROT(0x05),
+    /** IK接続先。 */
+    IKCONNECTED(0x06),
+    /** 非表示。 */
+    HIDDEN(0x07),
+    /** 捩り。 */
+    TWIST(0x08),
+    /** 回転連動。 */
+    LINKEDROT(0x09),
+    ;
+
+    private static final String FAMILY_NAME =
+            "jp.sourceforge.mikutoga.pmd.resources.BoneTypeName";
+
+    private final byte encoded;
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化int値
+     */
+    private BoneType(int code){
+        this((byte)code);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化byte値
+     */
+    private BoneType(byte code){
+        this.encoded = code;
+        return;
+    }
+
+    /**
+     * byte値からデコードする。
+     * @param code byte値
+     * @return デコードされた列挙子。該当するものがなければnull
+     */
+    public static BoneType decode(byte code){
+        BoneType result = null;
+
+        for(BoneType type : values()){
+            if(type.encode() == code){
+                result = type;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * byte値にエンコードする。
+     * @return byte値
+     */
+    public byte encode(){
+        return this.encoded;
+    }
+
+    /**
+     * デフォルトロケールでの表示名を返す。
+     * @return 表示名
+     */
+    public String getGuiName(){
+        Locale locale = Locale.getDefault();
+        return getGuiName(locale);
+    }
+
+    /**
+     * ロケールに準じた表示名を返す。
+     * @param locale ロケール。nullならデフォルトロケールと解釈される。
+     * @return 表示名
+     */
+    public String getGuiName(Locale locale){
+        if(locale == null) return getGuiName();
+        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);
+        String key = name();
+        String result = rb.getString(key);
+        return result;
+    }
+
+}
index 7ae17e9..63979b7 100644 (file)
@@ -1,95 +1,95 @@
-/*\r
- * 3d rotation (degree)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * XYZ3軸による回転量(degree)。\r
- * radianではなくdegree。(直角は90.0)\r
- */\r
-public class Deg3d {\r
-\r
-    private float xDeg;\r
-    private float yDeg;\r
-    private float zDeg;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public Deg3d(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X軸回転量を設定する。\r
-     * @param xDeg X軸回転量(degree)\r
-     */\r
-    public void setXDeg(float xDeg){\r
-        this.xDeg = xDeg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X軸回転量を返す。\r
-     * @return X軸回転量(degree)\r
-     */\r
-    public float getXDeg(){\r
-        return this.xDeg;\r
-    }\r
-\r
-    /**\r
-     * Y軸回転量を設定する。\r
-     * @param yDeg Y軸回転量(degree)\r
-     */\r
-    public void setYDeg(float yDeg){\r
-        this.yDeg = yDeg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y軸回転量を返す。\r
-     * @return Y軸回転量(degree)\r
-     */\r
-    public float getYDeg(){\r
-        return this.yDeg;\r
-    }\r
-\r
-    /**\r
-     * Z軸回転量を設定する。\r
-     * @param zDeg Z軸回転量(degree)\r
-     */\r
-    public void setZDeg(float zDeg){\r
-        this.zDeg = zDeg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Z軸回転量を返す。\r
-     * @return Z軸回転量(degree)\r
-     */\r
-    public float getZDeg(){\r
-        return this.zDeg;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("deg=[")\r
-              .append(this.xDeg).append(", ")\r
-              .append(this.yDeg).append(", ")\r
-              .append(this.zDeg).append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 3d rotation (degree)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * XYZ3軸による回転量(degree)。
+ * radianではなくdegree。(直角は90.0)
+ */
+public class Deg3d {
+
+    private float xDeg;
+    private float yDeg;
+    private float zDeg;
+
+    /**
+     * コンストラクタ。
+     */
+    public Deg3d(){
+        super();
+        return;
+    }
+
+    /**
+     * X軸回転量を設定する。
+     * @param xDeg X軸回転量(degree)
+     */
+    public void setXDeg(float xDeg){
+        this.xDeg = xDeg;
+        return;
+    }
+
+    /**
+     * X軸回転量を返す。
+     * @return X軸回転量(degree)
+     */
+    public float getXDeg(){
+        return this.xDeg;
+    }
+
+    /**
+     * Y軸回転量を設定する。
+     * @param yDeg Y軸回転量(degree)
+     */
+    public void setYDeg(float yDeg){
+        this.yDeg = yDeg;
+        return;
+    }
+
+    /**
+     * Y軸回転量を返す。
+     * @return Y軸回転量(degree)
+     */
+    public float getYDeg(){
+        return this.yDeg;
+    }
+
+    /**
+     * Z軸回転量を設定する。
+     * @param zDeg Z軸回転量(degree)
+     */
+    public void setZDeg(float zDeg){
+        this.zDeg = zDeg;
+        return;
+    }
+
+    /**
+     * Z軸回転量を返す。
+     * @return Z軸回転量(degree)
+     */
+    public float getZDeg(){
+        return this.zDeg;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("deg=[")
+              .append(this.xDeg).append(", ")
+              .append(this.yDeg).append(", ")
+              .append(this.zDeg).append(']');
+
+        return result.toString();
+    }
+
+}
index 3dbcf80..82538d2 100644 (file)
-/*\r
- * dynamics parameter\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * 剛体間力学演算の各種パラメータ。\r
- * 各剛体に設定可能なパラメータは\r
- * 「質量」、「移動減衰率」、「回転減衰率」、「反発力」、「摩擦力」の5種類。\r
- */\r
-public class DynamicsInfo {\r
-\r
-    /** 質量。 */\r
-    private float mass;\r
-    /** 移動減衰率。 */\r
-    private float dampingPos;\r
-    /** 回転減衰率。 */\r
-    private float dampingRot;\r
-    /** 反発力。 */\r
-    private float restitution;\r
-    /** 摩擦力。 */\r
-    private float friction;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public DynamicsInfo(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 質量を返す。\r
-     * @return 質量\r
-     */\r
-    public float getMass(){\r
-        return this.mass;\r
-    }\r
-\r
-    /**\r
-     * 質量を設定する。\r
-     * @param mass 質量\r
-     */\r
-    public void setMass(float mass){\r
-        this.mass = mass;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 移動減衰率を返す。\r
-     * @return 移動減衰率\r
-     */\r
-    public float getDampingPosition(){\r
-        return this.dampingPos;\r
-    }\r
-\r
-    /**\r
-     * 移動減衰率を設定する。\r
-     * @param damping 移動減衰率\r
-     */\r
-    public void setDampingPosition(float damping){\r
-        this.dampingPos = damping;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 回転減衰率を返す。\r
-     * @return 回転減衰率\r
-     */\r
-    public float getDampingRotation(){\r
-        return this.dampingRot;\r
-    }\r
-\r
-    /**\r
-     * 回転減衰率を設定する。\r
-     * @param damping 回転減衰率\r
-     */\r
-    public void setDampingRotation(float damping){\r
-        this.dampingRot = damping;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 反発力を返す。\r
-     * @return 反発力\r
-     */\r
-    public float getRestitution(){\r
-        return this.restitution;\r
-    }\r
-\r
-    /**\r
-     * 反発力を設定する。\r
-     * @param restitution 反発力\r
-     */\r
-    public void setRestitution(float restitution){\r
-        this.restitution = restitution;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 摩擦力を返す。\r
-     * @return 摩擦力\r
-     */\r
-    public float getFriction(){\r
-        return this.friction;\r
-    }\r
-\r
-    /**\r
-     * 摩擦力を設定する。\r
-     * @param friction 摩擦力\r
-     */\r
-    public void setFriction(float friction){\r
-        this.friction = friction;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("mass=").append(this.mass).append(", ");\r
-        result.append("damping(Pos)=").append(this.dampingPos).append(", ");\r
-        result.append("damping(Rot)=").append(this.dampingRot).append(", ");\r
-        result.append("restitution=").append(this.restitution).append(", ");\r
-        result.append("friction=").append(this.friction);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * dynamics parameter
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * 剛体間力学演算の各種パラメータ。
+ * 各剛体に設定可能なパラメータは
+ * 「質量」、「移動減衰率」、「回転減衰率」、「反発力」、「摩擦力」の5種類。
+ */
+public class DynamicsInfo {
+
+    /** 質量。 */
+    private float mass;
+    /** 移動減衰率。 */
+    private float dampingPos;
+    /** 回転減衰率。 */
+    private float dampingRot;
+    /** 反発力。 */
+    private float restitution;
+    /** 摩擦力。 */
+    private float friction;
+
+    /**
+     * コンストラクタ。
+     */
+    public DynamicsInfo(){
+        super();
+        return;
+    }
+
+    /**
+     * 質量を返す。
+     * @return 質量
+     */
+    public float getMass(){
+        return this.mass;
+    }
+
+    /**
+     * 質量を設定する。
+     * @param mass 質量
+     */
+    public void setMass(float mass){
+        this.mass = mass;
+        return;
+    }
+
+    /**
+     * 移動減衰率を返す。
+     * @return 移動減衰率
+     */
+    public float getDampingPosition(){
+        return this.dampingPos;
+    }
+
+    /**
+     * 移動減衰率を設定する。
+     * @param damping 移動減衰率
+     */
+    public void setDampingPosition(float damping){
+        this.dampingPos = damping;
+        return;
+    }
+
+    /**
+     * 回転減衰率を返す。
+     * @return 回転減衰率
+     */
+    public float getDampingRotation(){
+        return this.dampingRot;
+    }
+
+    /**
+     * 回転減衰率を設定する。
+     * @param damping 回転減衰率
+     */
+    public void setDampingRotation(float damping){
+        this.dampingRot = damping;
+        return;
+    }
+
+    /**
+     * 反発力を返す。
+     * @return 反発力
+     */
+    public float getRestitution(){
+        return this.restitution;
+    }
+
+    /**
+     * 反発力を設定する。
+     * @param restitution 反発力
+     */
+    public void setRestitution(float restitution){
+        this.restitution = restitution;
+        return;
+    }
+
+    /**
+     * 摩擦力を返す。
+     * @return 摩擦力
+     */
+    public float getFriction(){
+        return this.friction;
+    }
+
+    /**
+     * 摩擦力を設定する。
+     * @param friction 摩擦力
+     */
+    public void setFriction(float friction){
+        this.friction = friction;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("mass=").append(this.mass).append(", ");
+        result.append("damping(Pos)=").append(this.dampingPos).append(", ");
+        result.append("damping(Rot)=").append(this.dampingRot).append(", ");
+        result.append("restitution=").append(this.restitution).append(", ");
+        result.append("friction=").append(this.friction);
+
+        return result.toString();
+    }
+
+}
index 3b65a55..9ca055c 100644 (file)
-/*\r
- * IK chained bone\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-/**\r
- * IK連鎖ボーン群。\r
- */\r
-public class IKChain implements Iterable<BoneInfo> {\r
-\r
-    private BoneInfo ikBone;\r
-\r
-    private int ikDepth;\r
-    private float ikWeight;\r
-\r
-    private final List<BoneInfo> chainList = new ArrayList<BoneInfo>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public IKChain(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKボーンを設定する。\r
-     * @param bone IKボーン\r
-     */\r
-    public void setIkBone(BoneInfo bone){\r
-        this.ikBone = bone;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKボーンを返す。\r
-     * @return IKボーン\r
-     */\r
-    public BoneInfo getIkBone(){\r
-        return this.ikBone;\r
-    }\r
-\r
-    /**\r
-     * IK演算再帰深度を設定する。\r
-     * @param depth IK演算再帰深度\r
-     */\r
-    public void setIKDepth(int depth){\r
-        this.ikDepth = depth;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IK演算再帰深度を返す。\r
-     * @return IK演算再帰深度\r
-     */\r
-    public int getIKDepth(){\r
-        return this.ikDepth;\r
-    }\r
-\r
-    /**\r
-     * IKウェイトを設定する。\r
-     * @param weight IKウェイト\r
-     */\r
-    public void setIKWeight(float weight){\r
-        this.ikWeight = weight;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKウェイトを返す。\r
-     * @return IKウェイト\r
-     */\r
-    public float getIKWeight(){\r
-        return this.ikWeight;\r
-    }\r
-\r
-    /**\r
-     * IK連鎖ボーンリストを返す。\r
-     * 最初の要素は必ずIK接続先ボーン。それ以降はIK影響下ボーン。\r
-     * @return IK連鎖ボーンリスト\r
-     */\r
-    public List<BoneInfo> getChainedBoneList(){\r
-        return this.chainList;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<BoneInfo> iterator(){\r
-        return this.chainList.iterator();\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("IKChain");\r
-\r
-        result.append(" depth:").append(this.ikDepth);\r
-        result.append(" weight:").append(this.ikWeight);\r
-\r
-        result.append(" IKbone:").append(this.ikBone.getBoneName());\r
-\r
-        result.append(" [");\r
-\r
-        boolean chaindumped = false;\r
-        for(BoneInfo chain : this.chainList){\r
-            if(chaindumped) result.append(" => ");\r
-            result.append(chain.getBoneName());\r
-            chaindumped = true;\r
-        }\r
-\r
-        result.append("]");\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * IK chained bone
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * IK連鎖ボーン群。
+ */
+public class IKChain implements Iterable<BoneInfo> {
+
+    private BoneInfo ikBone;
+
+    private int ikDepth;
+    private float ikWeight;
+
+    private final List<BoneInfo> chainList = new ArrayList<BoneInfo>();
+
+    /**
+     * コンストラクタ。
+     */
+    public IKChain(){
+        super();
+        return;
+    }
+
+    /**
+     * IKボーンを設定する。
+     * @param bone IKボーン
+     */
+    public void setIkBone(BoneInfo bone){
+        this.ikBone = bone;
+        return;
+    }
+
+    /**
+     * IKボーンを返す。
+     * @return IKボーン
+     */
+    public BoneInfo getIkBone(){
+        return this.ikBone;
+    }
+
+    /**
+     * IK演算再帰深度を設定する。
+     * @param depth IK演算再帰深度
+     */
+    public void setIKDepth(int depth){
+        this.ikDepth = depth;
+        return;
+    }
+
+    /**
+     * IK演算再帰深度を返す。
+     * @return IK演算再帰深度
+     */
+    public int getIKDepth(){
+        return this.ikDepth;
+    }
+
+    /**
+     * IKウェイトを設定する。
+     * @param weight IKウェイト
+     */
+    public void setIKWeight(float weight){
+        this.ikWeight = weight;
+        return;
+    }
+
+    /**
+     * IKウェイトを返す。
+     * @return IKウェイト
+     */
+    public float getIKWeight(){
+        return this.ikWeight;
+    }
+
+    /**
+     * IK連鎖ボーンリストを返す。
+     * 最初の要素は必ずIK接続先ボーン。それ以降はIK影響下ボーン。
+     * @return IK連鎖ボーンリスト
+     */
+    public List<BoneInfo> getChainedBoneList(){
+        return this.chainList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<BoneInfo> iterator(){
+        return this.chainList.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("IKChain");
+
+        result.append(" depth:").append(this.ikDepth);
+        result.append(" weight:").append(this.ikWeight);
+
+        result.append(" IKbone:").append(this.ikBone.getBoneName());
+
+        result.append(" [");
+
+        boolean chaindumped = false;
+        for(BoneInfo chain : this.chainList){
+            if(chaindumped) result.append(" => ");
+            result.append(chain.getBoneName());
+            chaindumped = true;
+        }
+
+        result.append("]");
+
+        return result.toString();
+    }
+
+}
index 44165e2..10c6090 100644 (file)
-/*\r
- * joint information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-\r
-/**\r
- * 剛体間ジョイント情報。\r
- */\r
-public class JointInfo {\r
-\r
-    private final I18nText jointName = new I18nText();\r
-\r
-    private RigidInfo rigidA;\r
-    private RigidInfo rigidB;\r
-\r
-    private final Pos3d position = new Pos3d();\r
-    private final Rad3d rotation = new Rad3d();\r
-\r
-    private final Pos3d elaPosition = new Pos3d();\r
-    private final Deg3d elaRotation = new Deg3d();\r
-\r
-    private final TripletRange posRange = new TripletRange();\r
-    private final TripletRange rotRange = new TripletRange();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public JointInfo(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ジョイント名を返す。\r
-     * @return ジョイント名\r
-     */\r
-    public I18nText getJointName(){\r
-        return this.jointName;\r
-    }\r
-\r
-    /**\r
-     * 連結剛体Aを返す。\r
-     * @return 連結剛体A\r
-     */\r
-    public RigidInfo getRigidA(){\r
-        return this.rigidA;\r
-    }\r
-\r
-    /**\r
-     * 連結剛体Bを返す。\r
-     * @return 連結剛体B\r
-     */\r
-    public RigidInfo getRigidB(){\r
-        return this.rigidB;\r
-    }\r
-\r
-    /**\r
-     * 連結する剛体を設定する。\r
-     * @param rigidA 連結剛体A\r
-     * @param rigidB 連結剛体B\r
-     */\r
-    public void setRigidPair(RigidInfo rigidA, RigidInfo rigidB){\r
-        this.rigidA = rigidA;\r
-        this.rigidB = rigidB;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ジョイントの位置を返す。\r
-     * @return ジョイントの位置\r
-     */\r
-    public Pos3d getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * ジョイントの姿勢を返す。\r
-     * @return ジョイントの姿勢\r
-     */\r
-    public Rad3d getRotation(){\r
-        return this.rotation;\r
-    }\r
-\r
-    /**\r
-     * ジョイントのバネ位置を返す。\r
-     * @return ジョイントのバネ位置\r
-     */\r
-    public Pos3d getElasticPosition(){\r
-        return this.elaPosition;\r
-    }\r
-\r
-    /**\r
-     * ジョイントのバネ姿勢を返す。\r
-     * @return ジョイントのバネ姿勢\r
-     */\r
-    public Deg3d getElasticRotation(){\r
-        return this.elaRotation;\r
-    }\r
-\r
-    /**\r
-     * ジョイントの位置制約を返す。\r
-     * @return ジョイントの位置制約\r
-     */\r
-    public TripletRange getPositionRange(){\r
-        return this.posRange;\r
-    }\r
-\r
-    /**\r
-     * ジョイントの姿勢制約を返す。\r
-     * @return ジョイントの姿勢制約\r
-     */\r
-    public TripletRange getRotationRange(){\r
-        return this.rotRange;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Joint ");\r
-        result.append(this.jointName);\r
-        result.append("[")\r
-              .append(this.rigidA.getRigidName())\r
-              .append("<=>")\r
-              .append(this.rigidB.getRigidName())\r
-              .append("] ");\r
-        result.append(this.position).append(' ');\r
-        result.append(this.rotation).append(' ');\r
-\r
-        result.append("poslim{").append(this.posRange).append("} ");\r
-        result.append("rotlim{").append(this.rotRange).append("} ");\r
-\r
-        result.append("ela:").append(this.elaPosition).append(' ');\r
-        result.append("ela:").append(this.elaRotation);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * joint information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import jp.sourceforge.mikutoga.corelib.I18nText;
+
+/**
+ * 剛体間ジョイント情報。
+ */
+public class JointInfo {
+
+    private final I18nText jointName = new I18nText();
+
+    private RigidInfo rigidA;
+    private RigidInfo rigidB;
+
+    private final Pos3d position = new Pos3d();
+    private final Rad3d rotation = new Rad3d();
+
+    private final Pos3d elaPosition = new Pos3d();
+    private final Deg3d elaRotation = new Deg3d();
+
+    private final TripletRange posRange = new TripletRange();
+    private final TripletRange rotRange = new TripletRange();
+
+    /**
+     * コンストラクタ。
+     */
+    public JointInfo(){
+        super();
+        return;
+    }
+
+    /**
+     * ジョイント名を返す。
+     * @return ジョイント名
+     */
+    public I18nText getJointName(){
+        return this.jointName;
+    }
+
+    /**
+     * 連結剛体Aを返す。
+     * @return 連結剛体A
+     */
+    public RigidInfo getRigidA(){
+        return this.rigidA;
+    }
+
+    /**
+     * 連結剛体Bを返す。
+     * @return 連結剛体B
+     */
+    public RigidInfo getRigidB(){
+        return this.rigidB;
+    }
+
+    /**
+     * 連結する剛体を設定する。
+     * @param rigidA 連結剛体A
+     * @param rigidB 連結剛体B
+     */
+    public void setRigidPair(RigidInfo rigidA, RigidInfo rigidB){
+        this.rigidA = rigidA;
+        this.rigidB = rigidB;
+        return;
+    }
+
+    /**
+     * ジョイントの位置を返す。
+     * @return ジョイントの位置
+     */
+    public Pos3d getPosition(){
+        return this.position;
+    }
+
+    /**
+     * ジョイントの姿勢を返す。
+     * @return ジョイントの姿勢
+     */
+    public Rad3d getRotation(){
+        return this.rotation;
+    }
+
+    /**
+     * ジョイントのバネ位置を返す。
+     * @return ジョイントのバネ位置
+     */
+    public Pos3d getElasticPosition(){
+        return this.elaPosition;
+    }
+
+    /**
+     * ジョイントのバネ姿勢を返す。
+     * @return ジョイントのバネ姿勢
+     */
+    public Deg3d getElasticRotation(){
+        return this.elaRotation;
+    }
+
+    /**
+     * ジョイントの位置制約を返す。
+     * @return ジョイントの位置制約
+     */
+    public TripletRange getPositionRange(){
+        return this.posRange;
+    }
+
+    /**
+     * ジョイントの姿勢制約を返す。
+     * @return ジョイントの姿勢制約
+     */
+    public TripletRange getRotationRange(){
+        return this.rotRange;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Joint ");
+        result.append(this.jointName);
+        result.append("[")
+              .append(this.rigidA.getRigidName())
+              .append("<=>")
+              .append(this.rigidB.getRigidName())
+              .append("] ");
+        result.append(this.position).append(' ');
+        result.append(this.rotation).append(' ');
+
+        result.append("poslim{").append(this.posRange).append("} ");
+        result.append("rotlim{").append(this.rotRange).append("} ");
+
+        result.append("ela:").append(this.elaPosition).append(' ');
+        result.append("ela:").append(this.elaRotation);
+
+        return result.toString();
+    }
+
+}
index c59d861..17b1f48 100644 (file)
-/*\r
- * material information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.awt.Color;\r
-import java.awt.Transparency;\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-\r
-/**\r
- * マテリアル素材情報。\r
- */\r
-public class Material implements Iterable<Surface> {\r
-\r
-    private final I18nText materialName = new I18nText();\r
-\r
-    private Color diffuseColor;\r
-\r
-    private Color specularColor;\r
-    private float shininess;\r
-\r
-    private Color ambientColor;\r
-\r
-    private final ShadeInfo shadeInfo = new ShadeInfo();\r
-\r
-    private boolean edgeAppearance = true;\r
-\r
-    private final List<Surface> surfaceList = new ArrayList<Surface>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public Material(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 色を不透明化する。\r
-     * @param color 色\r
-     * @return 不透明化した色。引数と同じ場合もありうる。\r
-     */\r
-    private static Color forceOpaque(Color color){\r
-        if(color.getTransparency() == Transparency.OPAQUE){\r
-            return color;\r
-        }\r
-\r
-        float[] rgba = new float[4];\r
-        color.getRGBColorComponents(rgba);\r
-\r
-        Color result = new Color(rgba[0], rgba[1], rgba[2], 1.0f);\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * マテリアル名を返す。\r
-     * PMDEditorのみでのサポート?\r
-     * @return マテリアル名\r
-     */\r
-    public I18nText getMaterialName(){\r
-        return this.materialName;\r
-    }\r
-\r
-    /**\r
-     * 拡散光を設定する。\r
-     * アルファ成分も反映される。\r
-     * @param color 拡散光\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setDiffuseColor(Color color) throws NullPointerException{\r
-        if(color == null) throw new NullPointerException();\r
-        this.diffuseColor = color;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 拡散光を返す。\r
-     * @return 拡散光\r
-     */\r
-    public Color getDiffuseColor(){\r
-        return this.diffuseColor;\r
-    }\r
-\r
-    /**\r
-     * 反射光を設定する。\r
-     * 透過成分があれば不透明化される。\r
-     * @param color 反射光\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setSpecularColor(Color color)\r
-            throws NullPointerException{\r
-        if(color == null) throw new NullPointerException();\r
-        this.specularColor = forceOpaque(color);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 反射光を返す。\r
-     * @return 反射光\r
-     */\r
-    public Color getSpecularColor(){\r
-        return this.specularColor;\r
-    }\r
-\r
-    /**\r
-     * 環境光を設定する。\r
-     * 透過成分があれば不透明化される。\r
-     * @param color 環境光\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setAmbientColor(Color color)\r
-            throws NullPointerException{\r
-        if(color == null) throw new NullPointerException();\r
-        this.ambientColor = forceOpaque(color);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 環境光を返す。\r
-     * @return 環境光\r
-     */\r
-    public Color getAmbientColor(){\r
-        return this.ambientColor;\r
-    }\r
-\r
-    /**\r
-     * 光沢強度を設定する。\r
-     * MMDで用いられるのは1.0〜15.0あたり。\r
-     * @param shininess 光沢強度\r
-     */\r
-    public void setShininess(float shininess){\r
-        this.shininess = shininess;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 光沢強度を返す。\r
-     * @return 光沢強度\r
-     */\r
-    public float getShininess(){\r
-        return this.shininess;\r
-    }\r
-\r
-    /**\r
-     * シェーディング設定を返す。\r
-     * @return シェーディング設定\r
-     */\r
-    public ShadeInfo getShadeInfo(){\r
-        return this.shadeInfo;\r
-    }\r
-\r
-    /**\r
-     * エッジを表示するか設定する。\r
-     * 頂点単位の設定より優先度は低い。\r
-     * @param show 表示するならtrue\r
-     */\r
-    public void setEdgeAppearance(boolean show){\r
-        this.edgeAppearance = show;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * エッジを表示するか判定する。\r
-     * 頂点単位の設定より優先度は低い。\r
-     * @return 表示するならtrue\r
-     */\r
-    public boolean getEdgeAppearance(){\r
-        return this.edgeAppearance;\r
-    }\r
-\r
-    /**\r
-     * 面リストを返す。\r
-     * @return 面リスト\r
-     */\r
-    public List<Surface> getSurfaceList(){\r
-        return this.surfaceList;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<Surface> iterator(){\r
-        return this.surfaceList.iterator();\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Material ");\r
-\r
-        float[] rgba = new float[4];\r
-\r
-        this.diffuseColor.getRGBComponents(rgba);\r
-        result.append("diffuse=[")\r
-              .append(rgba[0]).append(", ")\r
-              .append(rgba[1]).append(", ")\r
-              .append(rgba[2]).append(", ")\r
-              .append(rgba[3]).append(']')\r
-              .append(' ');\r
-\r
-        this.specularColor.getRGBComponents(rgba);\r
-        result.append("specular=[")\r
-              .append(rgba[0]).append(", ")\r
-              .append(rgba[1]).append(", ")\r
-              .append(rgba[2]).append(", ")\r
-              .append(rgba[3]).append(']')\r
-              .append(' ');\r
-\r
-        this.ambientColor.getRGBComponents(rgba);\r
-        result.append("ambient=[")\r
-              .append(rgba[0]).append(", ")\r
-              .append(rgba[1]).append(", ")\r
-              .append(rgba[2]).append(", ")\r
-              .append(rgba[3]).append(']')\r
-              .append(' ');\r
-\r
-        result.append("shininess=")\r
-              .append(this.shininess)\r
-              .append(' ');\r
-        result.append("edge=")\r
-              .append(this.edgeAppearance)\r
-              .append(' ');\r
-        result.append("surfaces=")\r
-              .append(this.surfaceList.size())\r
-              .append(' ');\r
-        result.append(this.shadeInfo);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * material information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.awt.Color;
+import java.awt.Transparency;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+
+/**
+ * マテリアル素材情報。
+ */
+public class Material implements Iterable<Surface> {
+
+    private final I18nText materialName = new I18nText();
+
+    private Color diffuseColor;
+
+    private Color specularColor;
+    private float shininess;
+
+    private Color ambientColor;
+
+    private final ShadeInfo shadeInfo = new ShadeInfo();
+
+    private boolean edgeAppearance = true;
+
+    private final List<Surface> surfaceList = new ArrayList<Surface>();
+
+    /**
+     * コンストラクタ。
+     */
+    public Material(){
+        super();
+        return;
+    }
+
+    /**
+     * 色を不透明化する。
+     * @param color 色
+     * @return 不透明化した色。引数と同じ場合もありうる。
+     */
+    private static Color forceOpaque(Color color){
+        if(color.getTransparency() == Transparency.OPAQUE){
+            return color;
+        }
+
+        float[] rgba = new float[4];
+        color.getRGBColorComponents(rgba);
+
+        Color result = new Color(rgba[0], rgba[1], rgba[2], 1.0f);
+
+        return result;
+    }
+
+    /**
+     * マテリアル名を返す。
+     * PMDEditorのみでのサポート?
+     * @return マテリアル名
+     */
+    public I18nText getMaterialName(){
+        return this.materialName;
+    }
+
+    /**
+     * 拡散光を設定する。
+     * アルファ成分も反映される。
+     * @param color 拡散光
+     * @throws NullPointerException 引数がnull
+     */
+    public void setDiffuseColor(Color color) throws NullPointerException{
+        if(color == null) throw new NullPointerException();
+        this.diffuseColor = color;
+        return;
+    }
+
+    /**
+     * 拡散光を返す。
+     * @return 拡散光
+     */
+    public Color getDiffuseColor(){
+        return this.diffuseColor;
+    }
+
+    /**
+     * 反射光を設定する。
+     * 透過成分があれば不透明化される。
+     * @param color 反射光
+     * @throws NullPointerException 引数がnull
+     */
+    public void setSpecularColor(Color color)
+            throws NullPointerException{
+        if(color == null) throw new NullPointerException();
+        this.specularColor = forceOpaque(color);
+        return;
+    }
+
+    /**
+     * 反射光を返す。
+     * @return 反射光
+     */
+    public Color getSpecularColor(){
+        return this.specularColor;
+    }
+
+    /**
+     * 環境光を設定する。
+     * 透過成分があれば不透明化される。
+     * @param color 環境光
+     * @throws NullPointerException 引数がnull
+     */
+    public void setAmbientColor(Color color)
+            throws NullPointerException{
+        if(color == null) throw new NullPointerException();
+        this.ambientColor = forceOpaque(color);
+        return;
+    }
+
+    /**
+     * 環境光を返す。
+     * @return 環境光
+     */
+    public Color getAmbientColor(){
+        return this.ambientColor;
+    }
+
+    /**
+     * 光沢強度を設定する。
+     * MMDで用いられるのは1.0〜15.0あたり。
+     * @param shininess 光沢強度
+     */
+    public void setShininess(float shininess){
+        this.shininess = shininess;
+        return;
+    }
+
+    /**
+     * 光沢強度を返す。
+     * @return 光沢強度
+     */
+    public float getShininess(){
+        return this.shininess;
+    }
+
+    /**
+     * シェーディング設定を返す。
+     * @return シェーディング設定
+     */
+    public ShadeInfo getShadeInfo(){
+        return this.shadeInfo;
+    }
+
+    /**
+     * エッジを表示するか設定する。
+     * 頂点単位の設定より優先度は低い。
+     * @param show 表示するならtrue
+     */
+    public void setEdgeAppearance(boolean show){
+        this.edgeAppearance = show;
+        return;
+    }
+
+    /**
+     * エッジを表示するか判定する。
+     * 頂点単位の設定より優先度は低い。
+     * @return 表示するならtrue
+     */
+    public boolean getEdgeAppearance(){
+        return this.edgeAppearance;
+    }
+
+    /**
+     * 面リストを返す。
+     * @return 面リスト
+     */
+    public List<Surface> getSurfaceList(){
+        return this.surfaceList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<Surface> iterator(){
+        return this.surfaceList.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Material ");
+
+        float[] rgba = new float[4];
+
+        this.diffuseColor.getRGBComponents(rgba);
+        result.append("diffuse=[")
+              .append(rgba[0]).append(", ")
+              .append(rgba[1]).append(", ")
+              .append(rgba[2]).append(", ")
+              .append(rgba[3]).append(']')
+              .append(' ');
+
+        this.specularColor.getRGBComponents(rgba);
+        result.append("specular=[")
+              .append(rgba[0]).append(", ")
+              .append(rgba[1]).append(", ")
+              .append(rgba[2]).append(", ")
+              .append(rgba[3]).append(']')
+              .append(' ');
+
+        this.ambientColor.getRGBComponents(rgba);
+        result.append("ambient=[")
+              .append(rgba[0]).append(", ")
+              .append(rgba[1]).append(", ")
+              .append(rgba[2]).append(", ")
+              .append(rgba[3]).append(']')
+              .append(' ');
+
+        result.append("shininess=")
+              .append(this.shininess)
+              .append(' ');
+        result.append("edge=")
+              .append(this.edgeAppearance)
+              .append(' ');
+        result.append("surfaces=")
+              .append(this.surfaceList.size())
+              .append(' ');
+        result.append(this.shadeInfo);
+
+        return result.toString();
+    }
+
+}
index fdab975..e041564 100644 (file)
-/*\r
- * morph information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * 個別モーフ情報。\r
- */\r
-public class MorphPart implements SerialNumbered, Iterable<MorphVertex> {\r
-\r
-    private final I18nText morphName = new I18nText();\r
-\r
-    private MorphType type;\r
-\r
-    private final List<MorphVertex> morphVertexList =\r
-            new ArrayList<MorphVertex>();\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public MorphPart(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフ名を返す。\r
-     * @return モーフ名\r
-     */\r
-    public I18nText getMorphName(){\r
-        return this.morphName;\r
-    }\r
-\r
-    /**\r
-     * モーフ種別を設定する。\r
-     * @param typeArg モーフ種別\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setMorphType(MorphType typeArg) throws NullPointerException{\r
-        if(typeArg == null) throw new NullPointerException();\r
-        this.type = typeArg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフ種別を返す。\r
-     * @return モーフ種別。\r
-     */\r
-    public MorphType getMorphType(){\r
-        return this.type;\r
-    }\r
-\r
-    /**\r
-     * モーフ頂点情報リストを返す。\r
-     * @return モーフ頂点情報リスト\r
-     */\r
-    public List<MorphVertex> getMorphVertexList(){\r
-        return this.morphVertexList;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<MorphVertex> iterator(){\r
-        return this.morphVertexList.iterator();\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Morph(").append(this.morphName).append(") ");\r
-        result.append("type=").append(this.type);\r
-        result.append(" vertexNum=").append(this.morphVertexList.size());\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * morph information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * 個別モーフ情報。
+ */
+public class MorphPart implements SerialNumbered, Iterable<MorphVertex> {
+
+    private final I18nText morphName = new I18nText();
+
+    private MorphType type;
+
+    private final List<MorphVertex> morphVertexList =
+            new ArrayList<MorphVertex>();
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public MorphPart(){
+        super();
+        return;
+    }
+
+    /**
+     * モーフ名を返す。
+     * @return モーフ名
+     */
+    public I18nText getMorphName(){
+        return this.morphName;
+    }
+
+    /**
+     * モーフ種別を設定する。
+     * @param typeArg モーフ種別
+     * @throws NullPointerException 引数がnull
+     */
+    public void setMorphType(MorphType typeArg) throws NullPointerException{
+        if(typeArg == null) throw new NullPointerException();
+        this.type = typeArg;
+        return;
+    }
+
+    /**
+     * モーフ種別を返す。
+     * @return モーフ種別。
+     */
+    public MorphType getMorphType(){
+        return this.type;
+    }
+
+    /**
+     * モーフ頂点情報リストを返す。
+     * @return モーフ頂点情報リスト
+     */
+    public List<MorphVertex> getMorphVertexList(){
+        return this.morphVertexList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<MorphVertex> iterator(){
+        return this.morphVertexList.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Morph(").append(this.morphName).append(") ");
+        result.append("type=").append(this.type);
+        result.append(" vertexNum=").append(this.morphVertexList.size());
+
+        return result.toString();
+    }
+
+}
index 5dba949..b9e6358 100644 (file)
-/*\r
- * morph type\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Locale;\r
-import java.util.ResourceBundle;\r
-\r
-/**\r
- * モーフ種別。\r
- * <ul>\r
- * <li>0:base\r
- * <li>1:まゆ\r
- * <li>2:目\r
- * <li>3:リップ\r
- * <li>4:その他\r
- * </ul>\r
- */\r
-public enum MorphType {\r
-\r
-    /** base。 */\r
-    BASE(0x00),\r
-    /** まゆ。 */\r
-    EYEBROW(0x01),\r
-    /** 目。 */\r
-    EYE(0x02),\r
-    /** リップ。 */\r
-    LIP(0x03),\r
-    /** その他。 */\r
-    EXTRA(0x04),\r
-    ;\r
-\r
-    private static final String FAMILY_NAME =\r
-            "jp.sourceforge.mikutoga.pmd.resources.MorphTypeName";\r
-\r
-    private final byte encoded;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化int値\r
-     */\r
-    private MorphType(int code){\r
-        this((byte)code);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化byte値\r
-     */\r
-    private MorphType(byte code){\r
-        this.encoded = code;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値からデコードする。\r
-     * @param code byte値\r
-     * @return デコードされた列挙子。該当するものがなければnull\r
-     */\r
-    public static MorphType decode(byte code){\r
-        MorphType result = null;\r
-\r
-        for(MorphType type : values()){\r
-            if(type.encode() == code){\r
-                result = type;\r
-                break;\r
-            }\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * byte値にエンコードする。\r
-     * @return byte値\r
-     */\r
-    public byte encode(){\r
-        return this.encoded;\r
-    }\r
-\r
-    /**\r
-     * デフォルトロケールでの表示名を返す。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(){\r
-        Locale locale = Locale.getDefault();\r
-        return getGuiName(locale);\r
-    }\r
-\r
-    /**\r
-     * ロケールに準じた表示名を返す。\r
-     * @param locale ロケール。nullならデフォルトロケールと解釈される。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(Locale locale){\r
-        if(locale == null) return getGuiName();\r
-        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);\r
-        String key = name();\r
-        String result = rb.getString(key);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * モーフ種別がbaseか否か判定する。\r
-     * @return baseならtrue\r
-     */\r
-    public boolean isBase(){\r
-        if(this == BASE) return true;\r
-        return false;\r
-    }\r
-\r
-}\r
+/*
+ * morph type
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * モーフ種別。
+ * <ul>
+ * <li>0:base
+ * <li>1:まゆ
+ * <li>2:目
+ * <li>3:リップ
+ * <li>4:その他
+ * </ul>
+ */
+public enum MorphType {
+
+    /** base。 */
+    BASE(0x00),
+    /** まゆ。 */
+    EYEBROW(0x01),
+    /** 目。 */
+    EYE(0x02),
+    /** リップ。 */
+    LIP(0x03),
+    /** その他。 */
+    EXTRA(0x04),
+    ;
+
+    private static final String FAMILY_NAME =
+            "jp.sourceforge.mikutoga.pmd.resources.MorphTypeName";
+
+    private final byte encoded;
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化int値
+     */
+    private MorphType(int code){
+        this((byte)code);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化byte値
+     */
+    private MorphType(byte code){
+        this.encoded = code;
+        return;
+    }
+
+    /**
+     * byte値からデコードする。
+     * @param code byte値
+     * @return デコードされた列挙子。該当するものがなければnull
+     */
+    public static MorphType decode(byte code){
+        MorphType result = null;
+
+        for(MorphType type : values()){
+            if(type.encode() == code){
+                result = type;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * byte値にエンコードする。
+     * @return byte値
+     */
+    public byte encode(){
+        return this.encoded;
+    }
+
+    /**
+     * デフォルトロケールでの表示名を返す。
+     * @return 表示名
+     */
+    public String getGuiName(){
+        Locale locale = Locale.getDefault();
+        return getGuiName(locale);
+    }
+
+    /**
+     * ロケールに準じた表示名を返す。
+     * @param locale ロケール。nullならデフォルトロケールと解釈される。
+     * @return 表示名
+     */
+    public String getGuiName(Locale locale){
+        if(locale == null) return getGuiName();
+        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);
+        String key = name();
+        String result = rb.getString(key);
+        return result;
+    }
+
+    /**
+     * モーフ種別がbaseか否か判定する。
+     * @return baseならtrue
+     */
+    public boolean isBase(){
+        if(this == BASE) return true;
+        return false;
+    }
+
+}
index f883e3e..39951d6 100644 (file)
-/*\r
- * morph vertex information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Comparator;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * モーフアニメーションを構成する個別の頂点移動の情報。\r
- */\r
-public class MorphVertex implements SerialNumbered{\r
-\r
-    /** 頂点IDを昇順に順序づけるComaparator。 */\r
-    public static final Comparator<MorphVertex> VIDCOMPARATOR =\r
-            new VertexIdComparator();\r
-\r
-    private Vertex baseVertex;\r
-    private final Pos3d offset = new Pos3d();\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public MorphVertex(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 移動元頂点情報を返す。\r
-     * @return 移動元頂点\r
-     */\r
-    public Vertex getBaseVertex(){\r
-        return this.baseVertex;\r
-    }\r
-\r
-    /**\r
-     * 移動元頂点情報を設定する。\r
-     * @param vertex 移動元頂点\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setBaseVertex(Vertex vertex) throws NullPointerException{\r
-        if(vertex == null) throw new NullPointerException();\r
-        this.baseVertex = vertex;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 頂点移動量を返す。\r
-     * @return 頂点移動量\r
-     */\r
-    public Pos3d getOffset(){\r
-        return this.offset;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("vid(")\r
-              .append(this.baseVertex.getSerialNumber())\r
-              .append(") ");\r
-        result.append(this.baseVertex.getPosition());\r
-        result.append(" >> ");\r
-        result.append(this.offset);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-    /**\r
-     * 頂点IDによる比較子Comparator。\r
-     */\r
-    private static final class VertexIdComparator\r
-            implements Comparator<MorphVertex> {\r
-\r
-        /**\r
-         * コンストラクタ。\r
-         */\r
-        private VertexIdComparator(){\r
-            super();\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param o1 {@inheritDoc}\r
-         * @param o2 {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public int compare(MorphVertex o1, MorphVertex o2){\r
-            if(o1 == o2) return 0;\r
-            if(o1 == null) return -1;\r
-            if(o2 == null) return +1;\r
-\r
-            int ser1 = o1.getBaseVertex().getSerialNumber();\r
-            int ser2 = o2.getBaseVertex().getSerialNumber();\r
-\r
-            return ser1 - ser2;\r
-        }\r
-\r
-    }\r
-\r
-}\r
+/*
+ * morph vertex information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Comparator;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * モーフアニメーションを構成する個別の頂点移動の情報。
+ */
+public class MorphVertex implements SerialNumbered{
+
+    /** 頂点IDを昇順に順序づけるComaparator。 */
+    public static final Comparator<MorphVertex> VIDCOMPARATOR =
+            new VertexIdComparator();
+
+    private Vertex baseVertex;
+    private final Pos3d offset = new Pos3d();
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public MorphVertex(){
+        super();
+        return;
+    }
+
+    /**
+     * 移動元頂点情報を返す。
+     * @return 移動元頂点
+     */
+    public Vertex getBaseVertex(){
+        return this.baseVertex;
+    }
+
+    /**
+     * 移動元頂点情報を設定する。
+     * @param vertex 移動元頂点
+     * @throws NullPointerException 引数がnull
+     */
+    public void setBaseVertex(Vertex vertex) throws NullPointerException{
+        if(vertex == null) throw new NullPointerException();
+        this.baseVertex = vertex;
+        return;
+    }
+
+    /**
+     * 頂点移動量を返す。
+     * @return 頂点移動量
+     */
+    public Pos3d getOffset(){
+        return this.offset;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("vid(")
+              .append(this.baseVertex.getSerialNumber())
+              .append(") ");
+        result.append(this.baseVertex.getPosition());
+        result.append(" >> ");
+        result.append(this.offset);
+
+        return result.toString();
+    }
+
+    /**
+     * 頂点IDによる比較子Comparator。
+     */
+    private static final class VertexIdComparator
+            implements Comparator<MorphVertex> {
+
+        /**
+         * コンストラクタ。
+         */
+        private VertexIdComparator(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param o1 {@inheritDoc}
+         * @param o2 {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public int compare(MorphVertex o1, MorphVertex o2){
+            if(o1 == o2) return 0;
+            if(o1 == null) return -1;
+            if(o2 == null) return +1;
+
+            int ser1 = o1.getBaseVertex().getSerialNumber();
+            int ser2 = o2.getBaseVertex().getSerialNumber();
+
+            return ser1 - ser2;
+        }
+
+    }
+
+}
index d6dd882..25aebb5 100644 (file)
-/*\r
- * PMD model\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.EnumMap;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.RandomAccess;\r
-import java.util.Set;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-\r
-/**\r
- * PMDモデルファイル一式に相当するもの。\r
- * 様々な基本構造のリストの集合から構成される。\r
- */\r
-public class PmdModel {\r
-\r
-    /** デフォルトのヘッダバージョン。 */\r
-    public static final float DEF_HEADERVER = 1.0f;\r
-\r
-    private float headerVersion = DEF_HEADERVER;\r
-\r
-    private final I18nText modelName = new I18nText();\r
-    private final I18nText description = new I18nText();\r
-\r
-    private final List<Vertex> vertexList = new ArrayList<Vertex>();\r
-    private final List<Surface> surfaceList = new ArrayList<Surface>();\r
-    private final List<Material> materialList = new LinkedList<Material>();\r
-\r
-    private final List<BoneInfo> boneList = new ArrayList<BoneInfo>();\r
-    private final List<BoneGroup> boneGroupList = new ArrayList<BoneGroup>();\r
-\r
-    private final List<IKChain> ikChainList = new ArrayList<IKChain>();\r
-\r
-    private final Map<MorphType, List<MorphPart>> morphMap =\r
-            new EnumMap<MorphType, List<MorphPart>>(MorphType.class);\r
-\r
-    private final List<RigidInfo> rigidList = new ArrayList<RigidInfo>();\r
-    private final List<RigidGroup> rigidGroupList =\r
-            new ArrayList<RigidGroup>();\r
-\r
-    private final List<JointInfo> jointList = new ArrayList<JointInfo>();\r
-\r
-    private ToonMap toonMap = new ToonMap();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public PmdModel(){\r
-        super();\r
-\r
-        assert this.vertexList instanceof RandomAccess;\r
-        assert this.surfaceList instanceof RandomAccess;\r
-\r
-        this.morphMap.put(MorphType.EYEBROW, new ArrayList<MorphPart>());\r
-        this.morphMap.put(MorphType.EYE,     new ArrayList<MorphPart>());\r
-        this.morphMap.put(MorphType.LIP,     new ArrayList<MorphPart>());\r
-        this.morphMap.put(MorphType.EXTRA,   new ArrayList<MorphPart>());\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイルのヘッダバージョンを返す。\r
-     * @return PMDファイルのヘッダバージョン\r
-     */\r
-    public float getHeaderVersion(){\r
-        return this.headerVersion;\r
-    }\r
-\r
-    /**\r
-     * PMDファイルのヘッダバージョンを設定する。\r
-     * @param ver PMDファイルのヘッダバージョン\r
-     */\r
-    public void setHeaderVersion(float ver){\r
-        this.headerVersion = ver;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モデル名を返す。\r
-     * @return モデル名\r
-     */\r
-    public I18nText getModelName(){\r
-        return this.modelName;\r
-    }\r
-\r
-    /**\r
-     * モデル説明文を返す。\r
-     * 改行表現には{@literal \n}が用いられる\r
-     * @return モデル説明文\r
-     */\r
-    public I18nText getDescription(){\r
-        return this.description;\r
-    }\r
-\r
-    /**\r
-     * 頂点リストを返す。\r
-     * @return 頂点リスト。\r
-     */\r
-    public List<Vertex> getVertexList(){\r
-        return this.vertexList;\r
-    }\r
-\r
-    /**\r
-     * 面リストを返す。\r
-     * @return 面リスト\r
-     */\r
-    public List<Surface> getSurfaceList(){\r
-        return this.surfaceList;\r
-    }\r
-\r
-    /**\r
-     * 素材リストを返す。\r
-     * @return 素材リスト\r
-     */\r
-    public List<Material> getMaterialList(){\r
-        return this.materialList;\r
-    }\r
-\r
-    /**\r
-     * ボーンリストを返す。\r
-     * @return ボーンリスト\r
-     */\r
-    public List<BoneInfo> getBoneList(){\r
-        return this.boneList;\r
-    }\r
-\r
-    /**\r
-     * ボーングループリストを返す。\r
-     * @return ボーングループリスト\r
-     */\r
-    public List<BoneGroup> getBoneGroupList(){\r
-        return this.boneGroupList;\r
-    }\r
-\r
-    /**\r
-     * IKチェーンリストを返す。\r
-     * @return IKチェーンリスト\r
-     */\r
-    public List<IKChain> getIKChainList(){\r
-        return this.ikChainList;\r
-    }\r
-\r
-    /**\r
-     * 種類別モーフリストのマップを返す。\r
-     * @return 種類別モーフリストのマップ\r
-     */\r
-    public Map<MorphType, List<MorphPart>> getMorphMap(){\r
-        return this.morphMap;\r
-    }\r
-\r
-    /**\r
-     * 剛体リストを返す。\r
-     * @return 剛体リスト\r
-     */\r
-    public List<RigidInfo> getRigidList(){\r
-        return this.rigidList;\r
-    }\r
-\r
-    /**\r
-     * 剛体グループリストを返す。\r
-     * @return 剛体グループリスト。\r
-     */\r
-    public List<RigidGroup> getRigidGroupList(){\r
-        return this.rigidGroupList;\r
-    }\r
-\r
-    /**\r
-     * 剛体間ジョイントリストを返す。\r
-     * @return 剛体間ジョイントリスト\r
-     */\r
-    public List<JointInfo> getJointList(){\r
-        return this.jointList;\r
-    }\r
-\r
-    /**\r
-     * トゥーンファイルマップを返す。\r
-     * @return トゥーンファイルマップ\r
-     */\r
-    public ToonMap getToonMap(){\r
-        return this.toonMap;\r
-    }\r
-\r
-    /**\r
-     * トゥーンファイルマップを設定する。\r
-     * 各素材のシェーディングで参照するトゥーンファイルマップも更新される。\r
-     * @param map トゥーンファイルマップ\r
-     */\r
-    public void setToonMap(ToonMap map){\r
-        this.toonMap = map;\r
-        for(Material material : this.materialList){\r
-            ShadeInfo info = material.getShadeInfo();\r
-            info.setToonMap(this.toonMap);\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * このモデルがグローバル名を含むか判定する。\r
-     * ボーン名、ボーングループ名、モーフ名、モデル説明文が判定対象。\r
-     * @return グローバル名を持つならtrue\r
-     */\r
-    public boolean hasGlobalText(){\r
-        if(this.modelName.hasGlobalText()) return true;\r
-        if(this.description.hasGlobalText()) return true;\r
-\r
-        for(BoneInfo bone : this.boneList){\r
-            if(bone.getBoneName().hasGlobalText()) return true;\r
-        }\r
-\r
-        List<MorphType> typeList = new ArrayList<MorphType>();\r
-        typeList.addAll(this.morphMap.keySet());\r
-        for(MorphType type : typeList){\r
-            List<MorphPart> partList = this.morphMap.get(type);\r
-            for(MorphPart part : partList){\r
-                if(part.getMorphName().hasGlobalText()) return true;\r
-            }\r
-        }\r
-\r
-        for(BoneGroup group : this.boneGroupList){\r
-            if(group.getGroupName().hasGlobalText()) return true;\r
-        }\r
-\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * モーフで使われる全てのモーフ頂点のリストを返す。\r
-     * モーフ間で重複する頂点はマージされる。\r
-     * 頂点IDでソートされる。\r
-     * <p>\r
-     * 0から始まる通し番号がリナンバリングされる。\r
-     * 通し番号は返されるモーフ頂点リストの添え字番号と一致する。\r
-     * @return モーフに使われるモーフ頂点のリスト\r
-     */\r
-    public List<MorphVertex> mergeMorphVertex(){\r
-        List<MorphVertex> result = new ArrayList<MorphVertex>();\r
-\r
-        Set<Vertex> mergedVertexSet = new HashSet<Vertex>();\r
-        for(MorphType type : this.morphMap.keySet()){\r
-            if(type.isBase()) continue;\r
-            List<MorphPart> partList = this.morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                for(MorphVertex morphVertex : part){\r
-                    Vertex vertex = morphVertex.getBaseVertex();\r
-                    if(mergedVertexSet.contains(vertex)) continue;\r
-                    mergedVertexSet.add(vertex);\r
-                    result.add(morphVertex);\r
-                }\r
-            }\r
-        }\r
-\r
-        Collections.sort(result, MorphVertex.VIDCOMPARATOR);\r
-        for(int idx = 0; idx < result.size(); idx++){\r
-            MorphVertex morphVertex = result.get(idx);\r
-            morphVertex.setSerialNumber(idx);\r
-        }\r
-\r
-        Map<Vertex, MorphVertex> numberedMap =\r
-                new HashMap<Vertex, MorphVertex>();\r
-        for(MorphVertex morphVertex : result){\r
-            numberedMap.put(morphVertex.getBaseVertex(), morphVertex);\r
-        }\r
-\r
-        for(MorphType type : this.morphMap.keySet()){\r
-            if(type.isBase()) continue;\r
-            List<MorphPart> partList = this.morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                for(MorphVertex morphVertex : part){\r
-                    Vertex vertex = morphVertex.getBaseVertex();\r
-                    MorphVertex numbered = numberedMap.get(vertex);\r
-                    assert numbered != null;\r
-                    morphVertex.setSerialNumber(numbered.getSerialNumber());\r
-                }\r
-            }\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 永続化可能な状態へトリミングする。\r
-     * 各種オブジェクトの通し番号が変化する可能性がある。\r
-     */\r
-    public void trimming(){\r
-        List<Surface> trimmedSurfaceList = trimmingSurfaceList();\r
-        this.surfaceList.clear();\r
-        this.surfaceList.addAll(trimmedSurfaceList);\r
-\r
-        List<Vertex> trimmedVertexList = trimmingVertexList();\r
-        this.vertexList.clear();\r
-        this.vertexList.addAll(trimmedVertexList);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 面リストをトリミングする。\r
-     * 所属マテリアル順に再配置し、通し番号を割り振り直す。\r
-     * 所属マテリアルの無い面はリストの末端に配置される。\r
-     * 面リスト中のnullは削除され詰められる。\r
-     * @return トリミングされた面リスト\r
-     */\r
-    private List<Surface> trimmingSurfaceList(){\r
-        Set<Surface> materialedSurfaceSet = new HashSet<Surface>();\r
-        for(Material material : this.materialList){\r
-            if(material == null) continue;\r
-            for(Surface surface : material){\r
-                if(surface == null) continue;\r
-                materialedSurfaceSet.add(surface);\r
-            }\r
-        }\r
-\r
-        materialedSurfaceSet.removeAll(this.surfaceList);\r
-\r
-        List<Surface> result = new ArrayList<Surface>();\r
-        for(Surface surface : this.surfaceList){\r
-            if(surface == null) continue;\r
-            result.add(surface);\r
-        }\r
-\r
-        result.addAll(materialedSurfaceSet);\r
-\r
-        int serialNum = 0;\r
-        for(Surface surface : result){\r
-            surface.setSerialNumber(serialNum);\r
-            serialNum++;\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 頂点リストをトリミングする。\r
-     * 通し番号を振り直す。\r
-     * 所属面の無い頂点はリストの末端に配置される。\r
-     * 頂点リスト中のnullは削除され詰められる。\r
-     * @return トリミングされた頂点リスト\r
-     */\r
-    private List<Vertex> trimmingVertexList(){\r
-        Set<Vertex> surfacedVertexSet = new HashSet<Vertex>();\r
-        for(Surface surface : this.surfaceList){\r
-            if(surface == null) continue;\r
-            for(Vertex vertex : surface){\r
-                surfacedVertexSet.add(vertex);\r
-            }\r
-        }\r
-\r
-        surfacedVertexSet.removeAll(this.vertexList);\r
-\r
-        List<Vertex> result = new ArrayList<Vertex>();\r
-        for(Vertex vertex : this.vertexList){\r
-            if(vertex == null) continue;\r
-            result.add(vertex);\r
-        }\r
-\r
-        result.addAll(surfacedVertexSet);\r
-\r
-        int serialNum = 0;\r
-        for(Vertex vertex : result){\r
-            vertex.setSerialNumber(serialNum);\r
-            serialNum++;\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * PMD model
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.Set;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+
+/**
+ * PMDモデルファイル一式に相当するもの。
+ * 様々な基本構造のリストの集合から構成される。
+ */
+public class PmdModel {
+
+    /** デフォルトのヘッダバージョン。 */
+    public static final float DEF_HEADERVER = 1.0f;
+
+    private float headerVersion = DEF_HEADERVER;
+
+    private final I18nText modelName = new I18nText();
+    private final I18nText description = new I18nText();
+
+    private final List<Vertex> vertexList = new ArrayList<Vertex>();
+    private final List<Surface> surfaceList = new ArrayList<Surface>();
+    private final List<Material> materialList = new LinkedList<Material>();
+
+    private final List<BoneInfo> boneList = new ArrayList<BoneInfo>();
+    private final List<BoneGroup> boneGroupList = new ArrayList<BoneGroup>();
+
+    private final List<IKChain> ikChainList = new ArrayList<IKChain>();
+
+    private final Map<MorphType, List<MorphPart>> morphMap =
+            new EnumMap<MorphType, List<MorphPart>>(MorphType.class);
+
+    private final List<RigidInfo> rigidList = new ArrayList<RigidInfo>();
+    private final List<RigidGroup> rigidGroupList =
+            new ArrayList<RigidGroup>();
+
+    private final List<JointInfo> jointList = new ArrayList<JointInfo>();
+
+    private ToonMap toonMap = new ToonMap();
+
+    /**
+     * コンストラクタ。
+     */
+    public PmdModel(){
+        super();
+
+        assert this.vertexList instanceof RandomAccess;
+        assert this.surfaceList instanceof RandomAccess;
+
+        this.morphMap.put(MorphType.EYEBROW, new ArrayList<MorphPart>());
+        this.morphMap.put(MorphType.EYE,     new ArrayList<MorphPart>());
+        this.morphMap.put(MorphType.LIP,     new ArrayList<MorphPart>());
+        this.morphMap.put(MorphType.EXTRA,   new ArrayList<MorphPart>());
+
+        return;
+    }
+
+    /**
+     * PMDファイルのヘッダバージョンを返す。
+     * @return PMDファイルのヘッダバージョン
+     */
+    public float getHeaderVersion(){
+        return this.headerVersion;
+    }
+
+    /**
+     * PMDファイルのヘッダバージョンを設定する。
+     * @param ver PMDファイルのヘッダバージョン
+     */
+    public void setHeaderVersion(float ver){
+        this.headerVersion = ver;
+        return;
+    }
+
+    /**
+     * モデル名を返す。
+     * @return モデル名
+     */
+    public I18nText getModelName(){
+        return this.modelName;
+    }
+
+    /**
+     * モデル説明文を返す。
+     * 改行表現には{@literal \n}が用いられる
+     * @return モデル説明文
+     */
+    public I18nText getDescription(){
+        return this.description;
+    }
+
+    /**
+     * 頂点リストを返す。
+     * @return 頂点リスト。
+     */
+    public List<Vertex> getVertexList(){
+        return this.vertexList;
+    }
+
+    /**
+     * 面リストを返す。
+     * @return 面リスト
+     */
+    public List<Surface> getSurfaceList(){
+        return this.surfaceList;
+    }
+
+    /**
+     * 素材リストを返す。
+     * @return 素材リスト
+     */
+    public List<Material> getMaterialList(){
+        return this.materialList;
+    }
+
+    /**
+     * ボーンリストを返す。
+     * @return ボーンリスト
+     */
+    public List<BoneInfo> getBoneList(){
+        return this.boneList;
+    }
+
+    /**
+     * ボーングループリストを返す。
+     * @return ボーングループリスト
+     */
+    public List<BoneGroup> getBoneGroupList(){
+        return this.boneGroupList;
+    }
+
+    /**
+     * IKチェーンリストを返す。
+     * @return IKチェーンリスト
+     */
+    public List<IKChain> getIKChainList(){
+        return this.ikChainList;
+    }
+
+    /**
+     * 種類別モーフリストのマップを返す。
+     * @return 種類別モーフリストのマップ
+     */
+    public Map<MorphType, List<MorphPart>> getMorphMap(){
+        return this.morphMap;
+    }
+
+    /**
+     * 剛体リストを返す。
+     * @return 剛体リスト
+     */
+    public List<RigidInfo> getRigidList(){
+        return this.rigidList;
+    }
+
+    /**
+     * 剛体グループリストを返す。
+     * @return 剛体グループリスト。
+     */
+    public List<RigidGroup> getRigidGroupList(){
+        return this.rigidGroupList;
+    }
+
+    /**
+     * 剛体間ジョイントリストを返す。
+     * @return 剛体間ジョイントリスト
+     */
+    public List<JointInfo> getJointList(){
+        return this.jointList;
+    }
+
+    /**
+     * トゥーンファイルマップを返す。
+     * @return トゥーンファイルマップ
+     */
+    public ToonMap getToonMap(){
+        return this.toonMap;
+    }
+
+    /**
+     * トゥーンファイルマップを設定する。
+     * 各素材のシェーディングで参照するトゥーンファイルマップも更新される。
+     * @param map トゥーンファイルマップ
+     */
+    public void setToonMap(ToonMap map){
+        this.toonMap = map;
+        for(Material material : this.materialList){
+            ShadeInfo info = material.getShadeInfo();
+            info.setToonMap(this.toonMap);
+        }
+        return;
+    }
+
+    /**
+     * このモデルがグローバル名を含むか判定する。
+     * ボーン名、ボーングループ名、モーフ名、モデル説明文が判定対象。
+     * @return グローバル名を持つならtrue
+     */
+    public boolean hasGlobalText(){
+        if(this.modelName.hasGlobalText()) return true;
+        if(this.description.hasGlobalText()) return true;
+
+        for(BoneInfo bone : this.boneList){
+            if(bone.getBoneName().hasGlobalText()) return true;
+        }
+
+        List<MorphType> typeList = new ArrayList<MorphType>();
+        typeList.addAll(this.morphMap.keySet());
+        for(MorphType type : typeList){
+            List<MorphPart> partList = this.morphMap.get(type);
+            for(MorphPart part : partList){
+                if(part.getMorphName().hasGlobalText()) return true;
+            }
+        }
+
+        for(BoneGroup group : this.boneGroupList){
+            if(group.getGroupName().hasGlobalText()) return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * モーフで使われる全てのモーフ頂点のリストを返す。
+     * モーフ間で重複する頂点はマージされる。
+     * 頂点IDでソートされる。
+     * <p>
+     * 0から始まる通し番号がリナンバリングされる。
+     * 通し番号は返されるモーフ頂点リストの添え字番号と一致する。
+     * @return モーフに使われるモーフ頂点のリスト
+     */
+    public List<MorphVertex> mergeMorphVertex(){
+        List<MorphVertex> result = new ArrayList<MorphVertex>();
+
+        Set<Vertex> mergedVertexSet = new HashSet<Vertex>();
+        for(MorphType type : this.morphMap.keySet()){
+            if(type.isBase()) continue;
+            List<MorphPart> partList = this.morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                for(MorphVertex morphVertex : part){
+                    Vertex vertex = morphVertex.getBaseVertex();
+                    if(mergedVertexSet.contains(vertex)) continue;
+                    mergedVertexSet.add(vertex);
+                    result.add(morphVertex);
+                }
+            }
+        }
+
+        Collections.sort(result, MorphVertex.VIDCOMPARATOR);
+        for(int idx = 0; idx < result.size(); idx++){
+            MorphVertex morphVertex = result.get(idx);
+            morphVertex.setSerialNumber(idx);
+        }
+
+        Map<Vertex, MorphVertex> numberedMap =
+                new HashMap<Vertex, MorphVertex>();
+        for(MorphVertex morphVertex : result){
+            numberedMap.put(morphVertex.getBaseVertex(), morphVertex);
+        }
+
+        for(MorphType type : this.morphMap.keySet()){
+            if(type.isBase()) continue;
+            List<MorphPart> partList = this.morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                for(MorphVertex morphVertex : part){
+                    Vertex vertex = morphVertex.getBaseVertex();
+                    MorphVertex numbered = numberedMap.get(vertex);
+                    assert numbered != null;
+                    morphVertex.setSerialNumber(numbered.getSerialNumber());
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 永続化可能な状態へトリミングする。
+     * 各種オブジェクトの通し番号が変化する可能性がある。
+     */
+    public void trimming(){
+        List<Surface> trimmedSurfaceList = trimmingSurfaceList();
+        this.surfaceList.clear();
+        this.surfaceList.addAll(trimmedSurfaceList);
+
+        List<Vertex> trimmedVertexList = trimmingVertexList();
+        this.vertexList.clear();
+        this.vertexList.addAll(trimmedVertexList);
+
+        return;
+    }
+
+    /**
+     * 面リストをトリミングする。
+     * 所属マテリアル順に再配置し、通し番号を割り振り直す。
+     * 所属マテリアルの無い面はリストの末端に配置される。
+     * 面リスト中のnullは削除され詰められる。
+     * @return トリミングされた面リスト
+     */
+    private List<Surface> trimmingSurfaceList(){
+        Set<Surface> materialedSurfaceSet = new HashSet<Surface>();
+        for(Material material : this.materialList){
+            if(material == null) continue;
+            for(Surface surface : material){
+                if(surface == null) continue;
+                materialedSurfaceSet.add(surface);
+            }
+        }
+
+        materialedSurfaceSet.removeAll(this.surfaceList);
+
+        List<Surface> result = new ArrayList<Surface>();
+        for(Surface surface : this.surfaceList){
+            if(surface == null) continue;
+            result.add(surface);
+        }
+
+        result.addAll(materialedSurfaceSet);
+
+        int serialNum = 0;
+        for(Surface surface : result){
+            surface.setSerialNumber(serialNum);
+            serialNum++;
+        }
+
+        return result;
+    }
+
+    /**
+     * 頂点リストをトリミングする。
+     * 通し番号を振り直す。
+     * 所属面の無い頂点はリストの末端に配置される。
+     * 頂点リスト中のnullは削除され詰められる。
+     * @return トリミングされた頂点リスト
+     */
+    private List<Vertex> trimmingVertexList(){
+        Set<Vertex> surfacedVertexSet = new HashSet<Vertex>();
+        for(Surface surface : this.surfaceList){
+            if(surface == null) continue;
+            for(Vertex vertex : surface){
+                surfacedVertexSet.add(vertex);
+            }
+        }
+
+        surfacedVertexSet.removeAll(this.vertexList);
+
+        List<Vertex> result = new ArrayList<Vertex>();
+        for(Vertex vertex : this.vertexList){
+            if(vertex == null) continue;
+            result.add(vertex);
+        }
+
+        result.addAll(surfacedVertexSet);
+
+        int serialNum = 0;
+        for(Vertex vertex : result){
+            vertex.setSerialNumber(serialNum);
+            serialNum++;
+        }
+
+        return result;
+    }
+
+}
index dd1643d..6d77824 100644 (file)
@@ -1,88 +1,88 @@
-/*\r
- * 2D position\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * 二次元空間座標及び変量を表す。\r
- */\r
-public class Pos2d {\r
-\r
-    private float xPos;\r
-    private float yPos;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * [0,0]が設定される\r
-     */\r
-    public Pos2d(){\r
-        this(0.0f, 0.0f);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param xPos X座標\r
-     * @param yPos Y座標\r
-     */\r
-    public Pos2d(float xPos, float yPos){\r
-        super();\r
-        this.xPos = xPos;\r
-        this.yPos = yPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X座標を設定する。\r
-     * @param xPos X座標\r
-     */\r
-    public void setXPos(float xPos){\r
-        this.xPos = xPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X座標を返す。\r
-     * @return X座標\r
-     */\r
-    public float getXPos(){\r
-        return this.xPos;\r
-    }\r
-\r
-    /**\r
-     * Y座標を設定する。\r
-     * @param yPos Y座標\r
-     */\r
-    public void setYPos(float yPos){\r
-        this.yPos = yPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y座標を返す。\r
-     * @return Y座標\r
-     */\r
-    public float getYPos(){\r
-        return this.yPos;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("pos=[")\r
-              .append(this.xPos).append(", ")\r
-              .append(this.yPos).append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 2D position
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * 二次元空間座標及び変量を表す。
+ */
+public class Pos2d {
+
+    private float xPos;
+    private float yPos;
+
+    /**
+     * コンストラクタ。
+     * [0,0]が設定される
+     */
+    public Pos2d(){
+        this(0.0f, 0.0f);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param xPos X座標
+     * @param yPos Y座標
+     */
+    public Pos2d(float xPos, float yPos){
+        super();
+        this.xPos = xPos;
+        this.yPos = yPos;
+        return;
+    }
+
+    /**
+     * X座標を設定する。
+     * @param xPos X座標
+     */
+    public void setXPos(float xPos){
+        this.xPos = xPos;
+        return;
+    }
+
+    /**
+     * X座標を返す。
+     * @return X座標
+     */
+    public float getXPos(){
+        return this.xPos;
+    }
+
+    /**
+     * Y座標を設定する。
+     * @param yPos Y座標
+     */
+    public void setYPos(float yPos){
+        this.yPos = yPos;
+        return;
+    }
+
+    /**
+     * Y座標を返す。
+     * @return Y座標
+     */
+    public float getYPos(){
+        return this.yPos;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("pos=[")
+              .append(this.xPos).append(", ")
+              .append(this.yPos).append(']');
+
+        return result.toString();
+    }
+
+}
index aa5dbfe..12d6afc 100644 (file)
-/*\r
- * 3D position\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * 三次元空間座標及び変量を表す。\r
- */\r
-public class Pos3d {\r
-\r
-    private float xPos;\r
-    private float yPos;\r
-    private float zPos;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * [0,0,0]が設定される。\r
-     */\r
-    public Pos3d(){\r
-        this(0.0f, 0.0f, 0.0f);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param xPos X座標\r
-     * @param yPos Y座標\r
-     * @param zPos Z座標\r
-     */\r
-    public Pos3d(float xPos, float yPos, float zPos){\r
-        super();\r
-        this.xPos = xPos;\r
-        this.yPos = yPos;\r
-        this.zPos = zPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X座標を設定する。\r
-     * @param xPos X座標\r
-     */\r
-    public void setXPos(float xPos){\r
-        this.xPos = xPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X座標を返す。\r
-     * @return X座標\r
-     */\r
-    public float getXPos(){\r
-        return this.xPos;\r
-    }\r
-\r
-    /**\r
-     * Y座標を設定する。\r
-     * @param yPos Y座標\r
-     */\r
-    public void setYPos(float yPos){\r
-        this.yPos = yPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y座標を返す。\r
-     * @return Y座標\r
-     */\r
-    public float getYPos(){\r
-        return this.yPos;\r
-    }\r
-\r
-    /**\r
-     * Z座標を設定する。\r
-     * @param zPos Z座標\r
-     */\r
-    public void setZPos(float zPos){\r
-        this.zPos = zPos;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Z座標を返す。\r
-     * @return Z座標\r
-     */\r
-    public float getZPos(){\r
-        return this.zPos;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("pos=[")\r
-              .append(this.xPos).append(", ")\r
-              .append(this.yPos).append(", ")\r
-              .append(this.zPos).append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 3D position
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * 三次元空間座標及び変量を表す。
+ */
+public class Pos3d {
+
+    private float xPos;
+    private float yPos;
+    private float zPos;
+
+    /**
+     * コンストラクタ。
+     * [0,0,0]が設定される。
+     */
+    public Pos3d(){
+        this(0.0f, 0.0f, 0.0f);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param xPos X座標
+     * @param yPos Y座標
+     * @param zPos Z座標
+     */
+    public Pos3d(float xPos, float yPos, float zPos){
+        super();
+        this.xPos = xPos;
+        this.yPos = yPos;
+        this.zPos = zPos;
+        return;
+    }
+
+    /**
+     * X座標を設定する。
+     * @param xPos X座標
+     */
+    public void setXPos(float xPos){
+        this.xPos = xPos;
+        return;
+    }
+
+    /**
+     * X座標を返す。
+     * @return X座標
+     */
+    public float getXPos(){
+        return this.xPos;
+    }
+
+    /**
+     * Y座標を設定する。
+     * @param yPos Y座標
+     */
+    public void setYPos(float yPos){
+        this.yPos = yPos;
+        return;
+    }
+
+    /**
+     * Y座標を返す。
+     * @return Y座標
+     */
+    public float getYPos(){
+        return this.yPos;
+    }
+
+    /**
+     * Z座標を設定する。
+     * @param zPos Z座標
+     */
+    public void setZPos(float zPos){
+        this.zPos = zPos;
+        return;
+    }
+
+    /**
+     * Z座標を返す。
+     * @return Z座標
+     */
+    public float getZPos(){
+        return this.zPos;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("pos=[")
+              .append(this.xPos).append(", ")
+              .append(this.yPos).append(", ")
+              .append(this.zPos).append(']');
+
+        return result.toString();
+    }
+
+}
index 539dfc9..33dc633 100644 (file)
@@ -1,95 +1,95 @@
-/*\r
- * 3d rotation (radian)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * XYZ3軸による回転量(radian)。\r
- * degereeではなくradian。(直角はΠ/2)\r
- */\r
-public class Rad3d {\r
-\r
-    private float xRad;\r
-    private float yRad;\r
-    private float zRad;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public Rad3d(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X軸回転量を設定する。\r
-     * @param xRad X軸回転量(radian)\r
-     */\r
-    public void setXRad(float xRad){\r
-        this.xRad = xRad;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X軸回転量を返す。\r
-     * @return X軸回転量(radian)\r
-     */\r
-    public float getXRad(){\r
-        return this.xRad;\r
-    }\r
-\r
-    /**\r
-     * Y軸回転量を設定する。\r
-     * @param yRad Y軸回転量(radian)\r
-     */\r
-    public void setYRad(float yRad){\r
-        this.yRad = yRad;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y軸回転量を返す。\r
-     * @return Y軸回転量(radian)\r
-     */\r
-    public float getYRad(){\r
-        return this.yRad;\r
-    }\r
-\r
-    /**\r
-     * Z軸回転量を設定する。\r
-     * @param zRad Z軸回転量(radian)\r
-     */\r
-    public void setZRad(float zRad){\r
-        this.zRad = zRad;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Z軸回転量を返す。\r
-     * @return Z軸回転量(radian)\r
-     */\r
-    public float getZRad(){\r
-        return this.zRad;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("rad=[")\r
-              .append(this.xRad).append(", ")\r
-              .append(this.yRad).append(", ")\r
-              .append(this.zRad).append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 3d rotation (radian)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * XYZ3軸による回転量(radian)。
+ * degereeではなくradian。(直角はΠ/2)
+ */
+public class Rad3d {
+
+    private float xRad;
+    private float yRad;
+    private float zRad;
+
+    /**
+     * コンストラクタ。
+     */
+    public Rad3d(){
+        super();
+        return;
+    }
+
+    /**
+     * X軸回転量を設定する。
+     * @param xRad X軸回転量(radian)
+     */
+    public void setXRad(float xRad){
+        this.xRad = xRad;
+        return;
+    }
+
+    /**
+     * X軸回転量を返す。
+     * @return X軸回転量(radian)
+     */
+    public float getXRad(){
+        return this.xRad;
+    }
+
+    /**
+     * Y軸回転量を設定する。
+     * @param yRad Y軸回転量(radian)
+     */
+    public void setYRad(float yRad){
+        this.yRad = yRad;
+        return;
+    }
+
+    /**
+     * Y軸回転量を返す。
+     * @return Y軸回転量(radian)
+     */
+    public float getYRad(){
+        return this.yRad;
+    }
+
+    /**
+     * Z軸回転量を設定する。
+     * @param zRad Z軸回転量(radian)
+     */
+    public void setZRad(float zRad){
+        this.zRad = zRad;
+        return;
+    }
+
+    /**
+     * Z軸回転量を返す。
+     * @return Z軸回転量(radian)
+     */
+    public float getZRad(){
+        return this.zRad;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("rad=[")
+              .append(this.xRad).append(", ")
+              .append(this.yRad).append(", ")
+              .append(this.zRad).append(']');
+
+        return result.toString();
+    }
+
+}
index a17879d..663f06c 100644 (file)
-/*\r
- * rigid behavior type\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Locale;\r
-import java.util.ResourceBundle;\r
-\r
-/**\r
- * 剛体の振る舞い種別。\r
- * <ul>\r
- * <li>0x00:ボーン追従\r
- * <li>0x01:物理演算\r
- * <li>0x02:物理演算+ボーン位置合わせ\r
- * </ul>\r
- */\r
-public enum RigidBehaviorType {\r
-\r
-    /** ボーン追従。 */\r
-    FOLLOWBONE(0x00),\r
-    /** 物理演算。 */\r
-    ONLYDYNAMICS(0x01),\r
-    /** 物理演算+ボーン位置合わせ。 */\r
-    BONEDDYNAMICS(0x02),\r
-    ;\r
-\r
-    private static final String FAMILY_NAME =\r
-        "jp.sourceforge.mikutoga.pmd.resources.RigidBehaviorTypeName";\r
-\r
-    private final byte encoded;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化int値\r
-     */\r
-    private RigidBehaviorType(int code){\r
-        this((byte)code);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化byte値\r
-     */\r
-    private RigidBehaviorType(byte code){\r
-        this.encoded = code;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値からデコードする。\r
-     * @param code byte値\r
-     * @return デコードされた列挙子。該当するものがなければnull\r
-     */\r
-    public static RigidBehaviorType decode(byte code){\r
-        RigidBehaviorType result = null;\r
-\r
-        for(RigidBehaviorType type : values()){\r
-            if(type.encode() == code){\r
-                result = type;\r
-                break;\r
-            }\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * byte値にエンコードする。\r
-     * @return byte値\r
-     */\r
-    public byte encode(){\r
-        return this.encoded;\r
-    }\r
-\r
-    /**\r
-     * デフォルトロケールでの表示名を返す。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(){\r
-        Locale locale = Locale.getDefault();\r
-        return getGuiName(locale);\r
-    }\r
-\r
-    /**\r
-     * ロケールに準じた表示名を返す。\r
-     * @param locale ロケール。nullならデフォルトロケールと解釈される。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(Locale locale){\r
-        if(locale == null) return getGuiName();\r
-        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);\r
-        String key = name();\r
-        String result = rb.getString(key);\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * rigid behavior type
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * 剛体の振る舞い種別。
+ * <ul>
+ * <li>0x00:ボーン追従
+ * <li>0x01:物理演算
+ * <li>0x02:物理演算+ボーン位置合わせ
+ * </ul>
+ */
+public enum RigidBehaviorType {
+
+    /** ボーン追従。 */
+    FOLLOWBONE(0x00),
+    /** 物理演算。 */
+    ONLYDYNAMICS(0x01),
+    /** 物理演算+ボーン位置合わせ。 */
+    BONEDDYNAMICS(0x02),
+    ;
+
+    private static final String FAMILY_NAME =
+        "jp.sourceforge.mikutoga.pmd.resources.RigidBehaviorTypeName";
+
+    private final byte encoded;
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化int値
+     */
+    private RigidBehaviorType(int code){
+        this((byte)code);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化byte値
+     */
+    private RigidBehaviorType(byte code){
+        this.encoded = code;
+        return;
+    }
+
+    /**
+     * byte値からデコードする。
+     * @param code byte値
+     * @return デコードされた列挙子。該当するものがなければnull
+     */
+    public static RigidBehaviorType decode(byte code){
+        RigidBehaviorType result = null;
+
+        for(RigidBehaviorType type : values()){
+            if(type.encode() == code){
+                result = type;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * byte値にエンコードする。
+     * @return byte値
+     */
+    public byte encode(){
+        return this.encoded;
+    }
+
+    /**
+     * デフォルトロケールでの表示名を返す。
+     * @return 表示名
+     */
+    public String getGuiName(){
+        Locale locale = Locale.getDefault();
+        return getGuiName(locale);
+    }
+
+    /**
+     * ロケールに準じた表示名を返す。
+     * @param locale ロケール。nullならデフォルトロケールと解釈される。
+     * @return 表示名
+     */
+    public String getGuiName(Locale locale){
+        if(locale == null) return getGuiName();
+        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);
+        String key = name();
+        String result = rb.getString(key);
+        return result;
+    }
+
+}
index 9252523..93db41d 100644 (file)
-/*\r
- * rigid group\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * 剛体グループ情報。\r
- * 剛体間の衝突設定の対象となる。\r
- */\r
-public class RigidGroup implements SerialNumbered, Iterable<RigidInfo> {\r
-\r
-    private final List<RigidInfo> rigidList = new ArrayList<RigidInfo>();\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public RigidGroup(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 所属する剛体のリストを返す。\r
-     * @return 剛体リスト\r
-     */\r
-    public List<RigidInfo> getRigidList(){\r
-        return this.rigidList;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<RigidInfo> iterator(){\r
-        return this.rigidList.iterator();\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * グループ番号を返す。\r
-     * MMDでは1〜16までが使われる。\r
-     * 通し番号に1を加えた値と等しい。\r
-     * @return グループ番号\r
-     */\r
-    public int getGroupNumber(){\r
-        return this.serialNo + 1;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("RigidGroup(").append(getGroupNumber()).append(") [");\r
-\r
-        boolean dumped;\r
-\r
-        dumped = false;\r
-        for(RigidInfo rigid : this.rigidList){\r
-            if(dumped) result.append(", ");\r
-            result.append(rigid.getRigidName());\r
-            dumped = true;\r
-        }\r
-        result.append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * rigid group
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * 剛体グループ情報。
+ * 剛体間の衝突設定の対象となる。
+ */
+public class RigidGroup implements SerialNumbered, Iterable<RigidInfo> {
+
+    private final List<RigidInfo> rigidList = new ArrayList<RigidInfo>();
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public RigidGroup(){
+        super();
+        return;
+    }
+
+    /**
+     * 所属する剛体のリストを返す。
+     * @return 剛体リスト
+     */
+    public List<RigidInfo> getRigidList(){
+        return this.rigidList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<RigidInfo> iterator(){
+        return this.rigidList.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * グループ番号を返す。
+     * MMDでは1〜16までが使われる。
+     * 通し番号に1を加えた値と等しい。
+     * @return グループ番号
+     */
+    public int getGroupNumber(){
+        return this.serialNo + 1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("RigidGroup(").append(getGroupNumber()).append(") [");
+
+        boolean dumped;
+
+        dumped = false;
+        for(RigidInfo rigid : this.rigidList){
+            if(dumped) result.append(", ");
+            result.append(rigid.getRigidName());
+            dumped = true;
+        }
+        result.append(']');
+
+        return result.toString();
+    }
+
+}
index 42195d9..7f22adf 100644 (file)
-/*\r
- * rigid information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * 個別の剛体の情報。\r
- */\r
-public class RigidInfo implements SerialNumbered {\r
-\r
-    private final I18nText rigidName = new I18nText();\r
-\r
-    private RigidBehaviorType behaviorType = RigidBehaviorType.FOLLOWBONE;\r
-\r
-    private final RigidShape rigidShape = new RigidShape();\r
-    private final Pos3d position = new Pos3d();\r
-    private final Rad3d rotation = new Rad3d();\r
-\r
-    private BoneInfo linkedBone;\r
-\r
-    private final DynamicsInfo dynamicsInfo = new DynamicsInfo();\r
-\r
-    private final Collection<RigidGroup> throughGroupColl =\r
-            new ArrayList<RigidGroup>();\r
-\r
-    private RigidGroup rigidGroup;\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public RigidInfo(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体名を返す。\r
-     * @return 剛体名\r
-     */\r
-    public I18nText getRigidName(){\r
-        return this.rigidName;\r
-    }\r
-\r
-    /**\r
-     * 剛体の振る舞い種別を返す。\r
-     * @return 剛体の振る舞い種別\r
-     */\r
-    public RigidBehaviorType getBehaviorType(){\r
-        return this.behaviorType;\r
-    }\r
-\r
-    /**\r
-     * 剛体の振る舞い種別を設定する。\r
-     * @param type 剛体の振る舞い種別。\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setBehaviorType(RigidBehaviorType type)\r
-            throws NullPointerException{\r
-        if(type == null) throw new NullPointerException();\r
-        this.behaviorType = type;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体形状を返す。\r
-     * @return 剛体形状\r
-     */\r
-    public RigidShape getRigidShape(){\r
-        return this.rigidShape;\r
-    }\r
-\r
-    /**\r
-     * 剛体位置を返す。\r
-     * @return 剛体位置\r
-     */\r
-    public Pos3d getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * 剛体姿勢を返す。\r
-     * @return 剛体姿勢\r
-     */\r
-    public Rad3d getRotation(){\r
-        return this.rotation;\r
-    }\r
-\r
-    /**\r
-     * 接続ボーンを返す。\r
-     * @return 接続ボーン\r
-     */\r
-    public BoneInfo getLinkedBone(){\r
-        return this.linkedBone;\r
-    }\r
-\r
-    /**\r
-     * 接続ボーンを設定する。\r
-     * @param bone 接続ボーン\r
-     */\r
-    public void setLinkedBone(BoneInfo bone){\r
-        this.linkedBone = bone;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体の力学パラメータを返す。\r
-     * @return 力学パラメータ\r
-     */\r
-    public DynamicsInfo getDynamicsInfo(){\r
-        return this.dynamicsInfo;\r
-    }\r
-\r
-    /**\r
-     * 非衝突グループ集合を返す。\r
-     * @return 非衝突グループ集合\r
-     */\r
-    public Collection<RigidGroup> getThroughGroupColl(){\r
-        return this.throughGroupColl;\r
-    }\r
-\r
-    /**\r
-     * 所属する剛体グループを返す。\r
-     * @return 所属する剛体グループ\r
-     */\r
-    public RigidGroup getRigidGroup(){\r
-        return this.rigidGroup;\r
-    }\r
-\r
-    /**\r
-     * 所属する剛体グループを設定する。\r
-     * @param group 所属する剛体グループ\r
-     */\r
-    public void setRigidGroup(RigidGroup group){\r
-        this.rigidGroup = group;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        String boneName;\r
-        if(this.linkedBone == null){\r
-            boneName = "NOBONE";\r
-        }else{\r
-            boneName = this.linkedBone.getBoneName().toString();\r
-        }\r
-\r
-        result.append("Rigid(").append(this.rigidName).append(") ");\r
-        result.append("[=>")\r
-              .append(boneName)\r
-              .append("bone]");\r
-        result.append(" [").append(this.rigidShape).append("]");\r
-        result.append(" ").append(this.position);\r
-        result.append(" ").append(this.rotation);\r
-        result.append(" [").append(this.dynamicsInfo).append("]");\r
-        result.append("  [").append(this.behaviorType).append("]");\r
-\r
-        result.append(" through[");\r
-        boolean dumped = false;\r
-        for(RigidGroup group : this.throughGroupColl){\r
-            if(dumped) result.append(" ");\r
-            result.append(group.getGroupNumber());\r
-            dumped = true;\r
-        }\r
-        result.append("]");\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * rigid information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * 個別の剛体の情報。
+ */
+public class RigidInfo implements SerialNumbered {
+
+    private final I18nText rigidName = new I18nText();
+
+    private RigidBehaviorType behaviorType = RigidBehaviorType.FOLLOWBONE;
+
+    private final RigidShape rigidShape = new RigidShape();
+    private final Pos3d position = new Pos3d();
+    private final Rad3d rotation = new Rad3d();
+
+    private BoneInfo linkedBone;
+
+    private final DynamicsInfo dynamicsInfo = new DynamicsInfo();
+
+    private final Collection<RigidGroup> throughGroupColl =
+            new ArrayList<RigidGroup>();
+
+    private RigidGroup rigidGroup;
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public RigidInfo(){
+        super();
+        return;
+    }
+
+    /**
+     * 剛体名を返す。
+     * @return 剛体名
+     */
+    public I18nText getRigidName(){
+        return this.rigidName;
+    }
+
+    /**
+     * 剛体の振る舞い種別を返す。
+     * @return 剛体の振る舞い種別
+     */
+    public RigidBehaviorType getBehaviorType(){
+        return this.behaviorType;
+    }
+
+    /**
+     * 剛体の振る舞い種別を設定する。
+     * @param type 剛体の振る舞い種別。
+     * @throws NullPointerException 引数がnull
+     */
+    public void setBehaviorType(RigidBehaviorType type)
+            throws NullPointerException{
+        if(type == null) throw new NullPointerException();
+        this.behaviorType = type;
+        return;
+    }
+
+    /**
+     * 剛体形状を返す。
+     * @return 剛体形状
+     */
+    public RigidShape getRigidShape(){
+        return this.rigidShape;
+    }
+
+    /**
+     * 剛体位置を返す。
+     * @return 剛体位置
+     */
+    public Pos3d getPosition(){
+        return this.position;
+    }
+
+    /**
+     * 剛体姿勢を返す。
+     * @return 剛体姿勢
+     */
+    public Rad3d getRotation(){
+        return this.rotation;
+    }
+
+    /**
+     * 接続ボーンを返す。
+     * @return 接続ボーン
+     */
+    public BoneInfo getLinkedBone(){
+        return this.linkedBone;
+    }
+
+    /**
+     * 接続ボーンを設定する。
+     * @param bone 接続ボーン
+     */
+    public void setLinkedBone(BoneInfo bone){
+        this.linkedBone = bone;
+        return;
+    }
+
+    /**
+     * 剛体の力学パラメータを返す。
+     * @return 力学パラメータ
+     */
+    public DynamicsInfo getDynamicsInfo(){
+        return this.dynamicsInfo;
+    }
+
+    /**
+     * 非衝突グループ集合を返す。
+     * @return 非衝突グループ集合
+     */
+    public Collection<RigidGroup> getThroughGroupColl(){
+        return this.throughGroupColl;
+    }
+
+    /**
+     * 所属する剛体グループを返す。
+     * @return 所属する剛体グループ
+     */
+    public RigidGroup getRigidGroup(){
+        return this.rigidGroup;
+    }
+
+    /**
+     * 所属する剛体グループを設定する。
+     * @param group 所属する剛体グループ
+     */
+    public void setRigidGroup(RigidGroup group){
+        this.rigidGroup = group;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        String boneName;
+        if(this.linkedBone == null){
+            boneName = "NOBONE";
+        }else{
+            boneName = this.linkedBone.getBoneName().toString();
+        }
+
+        result.append("Rigid(").append(this.rigidName).append(") ");
+        result.append("[=>")
+              .append(boneName)
+              .append("bone]");
+        result.append(" [").append(this.rigidShape).append("]");
+        result.append(" ").append(this.position);
+        result.append(" ").append(this.rotation);
+        result.append(" [").append(this.dynamicsInfo).append("]");
+        result.append("  [").append(this.behaviorType).append("]");
+
+        result.append(" through[");
+        boolean dumped = false;
+        for(RigidGroup group : this.throughGroupColl){
+            if(dumped) result.append(" ");
+            result.append(group.getGroupNumber());
+            dumped = true;
+        }
+        result.append("]");
+
+        return result.toString();
+    }
+
+}
index 5906953..8af0765 100644 (file)
-/*\r
- * rigid shape information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * 剛体形状に関する情報。\r
- * 球及びカプセルの半径と箱の幅は同じ値が用いられる。\r
- */\r
-public class RigidShape {\r
-\r
-    private RigidShapeType type = RigidShapeType.BOX;\r
-    private float width  = 0.1f;\r
-    private float height = 0.1f;\r
-    private float depth  = 0.1f;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public RigidShape(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体形状種別を返す。\r
-     * @return 剛体形状種別\r
-     */\r
-    public RigidShapeType getShapeType(){\r
-        return this.type;\r
-    }\r
-\r
-    /**\r
-     * 剛体形状種別を設定する。\r
-     * @param typeArg 剛体形状種別\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setShapeType(RigidShapeType typeArg)\r
-            throws NullPointerException{\r
-        if(typeArg == null) throw new NullPointerException();\r
-        this.type = typeArg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 箱の幅を返す。\r
-     * @return 箱の幅\r
-     */\r
-    public float getWidth(){\r
-        return this.width;\r
-    }\r
-\r
-    /**\r
-     * 箱の幅を設定する。\r
-     * @param width 箱の幅\r
-     */\r
-    public void setWidth(float width){\r
-        this.width = width;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 箱及びカプセルの高さを返す。\r
-     * @return 箱及びカプセルの高さ\r
-     */\r
-    public float getHeight(){\r
-        return this.height;\r
-    }\r
-\r
-    /**\r
-     * 箱及びカプセルの高さを設定する。\r
-     * @param height 箱及びカプセルの高さ\r
-     */\r
-    public void setHeight(float height){\r
-        this.height = height;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 箱の奥行きを返す。\r
-     * @return 箱の奥行き\r
-     */\r
-    public float getDepth(){\r
-        return this.depth;\r
-    }\r
-\r
-    /**\r
-     * 箱の奥行きを設定する。\r
-     * @param depth 箱の奥行き\r
-     */\r
-    public void setDepth(float depth){\r
-        this.depth = depth;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 球及びカプセルの半径を返す。\r
-     * @return 球及びカプセルの半径\r
-     */\r
-    public float getRadius(){\r
-        return this.width;\r
-    }\r
-\r
-    /**\r
-     * 球及びカプセルの半径を設定する。\r
-     * @param radius 球及びカプセルの半径\r
-     */\r
-    public void setRadius(float radius){\r
-        this.width = radius;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append(this.type).append(' ');\r
-\r
-        switch(this.type){\r
-        case SPHERE:\r
-            result.append("r=").append(this.width);\r
-            break;\r
-        case BOX:\r
-            result.append("w=").append(this.width).append(", ");\r
-            result.append("h=").append(this.height).append(", ");\r
-            result.append("d=").append(this.depth);\r
-            break;\r
-        case CAPSULE:\r
-            result.append("r=").append(this.width).append(", ");\r
-            result.append("h=").append(this.height);\r
-            break;\r
-        default:\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-\r
-        return  result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * rigid shape information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * 剛体形状に関する情報。
+ * 球及びカプセルの半径と箱の幅は同じ値が用いられる。
+ */
+public class RigidShape {
+
+    private RigidShapeType type = RigidShapeType.BOX;
+    private float width  = 0.1f;
+    private float height = 0.1f;
+    private float depth  = 0.1f;
+
+    /**
+     * コンストラクタ。
+     */
+    public RigidShape(){
+        super();
+        return;
+    }
+
+    /**
+     * 剛体形状種別を返す。
+     * @return 剛体形状種別
+     */
+    public RigidShapeType getShapeType(){
+        return this.type;
+    }
+
+    /**
+     * 剛体形状種別を設定する。
+     * @param typeArg 剛体形状種別
+     * @throws NullPointerException 引数がnull
+     */
+    public void setShapeType(RigidShapeType typeArg)
+            throws NullPointerException{
+        if(typeArg == null) throw new NullPointerException();
+        this.type = typeArg;
+        return;
+    }
+
+    /**
+     * 箱の幅を返す。
+     * @return 箱の幅
+     */
+    public float getWidth(){
+        return this.width;
+    }
+
+    /**
+     * 箱の幅を設定する。
+     * @param width 箱の幅
+     */
+    public void setWidth(float width){
+        this.width = width;
+        return;
+    }
+
+    /**
+     * 箱及びカプセルの高さを返す。
+     * @return 箱及びカプセルの高さ
+     */
+    public float getHeight(){
+        return this.height;
+    }
+
+    /**
+     * 箱及びカプセルの高さを設定する。
+     * @param height 箱及びカプセルの高さ
+     */
+    public void setHeight(float height){
+        this.height = height;
+        return;
+    }
+
+    /**
+     * 箱の奥行きを返す。
+     * @return 箱の奥行き
+     */
+    public float getDepth(){
+        return this.depth;
+    }
+
+    /**
+     * 箱の奥行きを設定する。
+     * @param depth 箱の奥行き
+     */
+    public void setDepth(float depth){
+        this.depth = depth;
+        return;
+    }
+
+    /**
+     * 球及びカプセルの半径を返す。
+     * @return 球及びカプセルの半径
+     */
+    public float getRadius(){
+        return this.width;
+    }
+
+    /**
+     * 球及びカプセルの半径を設定する。
+     * @param radius 球及びカプセルの半径
+     */
+    public void setRadius(float radius){
+        this.width = radius;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append(this.type).append(' ');
+
+        switch(this.type){
+        case SPHERE:
+            result.append("r=").append(this.width);
+            break;
+        case BOX:
+            result.append("w=").append(this.width).append(", ");
+            result.append("h=").append(this.height).append(", ");
+            result.append("d=").append(this.depth);
+            break;
+        case CAPSULE:
+            result.append("r=").append(this.width).append(", ");
+            result.append("h=").append(this.height);
+            break;
+        default:
+            assert false;
+            throw new AssertionError();
+        }
+
+        return  result.toString();
+    }
+
+}
index 33df15d..ed12009 100644 (file)
-/*\r
- * rigid shape type\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Locale;\r
-import java.util.ResourceBundle;\r
-\r
-/**\r
- * 剛体の形状種別。\r
- * <ul>\r
- * <li>0x00:球\r
- * <li>0x01:箱\r
- * <li>0x02:カプセル\r
- * </ul>\r
- */\r
-public enum RigidShapeType {\r
-\r
-    /** 球。 */\r
-    SPHERE(0x00),\r
-    /** 箱。 */\r
-    BOX(0x01),\r
-    /** カプセル。 */\r
-    CAPSULE(0x02),\r
-    ;\r
-\r
-    private static final String FAMILY_NAME =\r
-            "jp.sourceforge.mikutoga.pmd.resources.RigidShapeTypeName";\r
-\r
-    private final byte encoded;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化int値\r
-     */\r
-    private RigidShapeType(int code){\r
-        this((byte)code);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param code 符号化byte値\r
-     */\r
-    private RigidShapeType(byte code){\r
-        this.encoded = code;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値からデコードする。\r
-     * @param code byte値\r
-     * @return デコードされた列挙子。該当するものがなければnull\r
-     */\r
-    public static RigidShapeType decode(byte code){\r
-        RigidShapeType result = null;\r
-\r
-        for(RigidShapeType type : values()){\r
-            if(type.encode() == code){\r
-                result = type;\r
-                break;\r
-            }\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * byte値にエンコードする。\r
-     * @return byte値\r
-     */\r
-    public byte encode(){\r
-        return this.encoded;\r
-    }\r
-\r
-    /**\r
-     * デフォルトロケールでの表示名を返す。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(){\r
-        Locale locale = Locale.getDefault();\r
-        return getGuiName(locale);\r
-    }\r
-\r
-    /**\r
-     * ロケールに準じた表示名を返す。\r
-     * @param locale ロケール。nullならデフォルトロケールと解釈される。\r
-     * @return 表示名\r
-     */\r
-    public String getGuiName(Locale locale){\r
-        if(locale == null) return getGuiName();\r
-        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);\r
-        String key = name();\r
-        String result = rb.getString(key);\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * rigid shape type
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * 剛体の形状種別。
+ * <ul>
+ * <li>0x00:球
+ * <li>0x01:箱
+ * <li>0x02:カプセル
+ * </ul>
+ */
+public enum RigidShapeType {
+
+    /** 球。 */
+    SPHERE(0x00),
+    /** 箱。 */
+    BOX(0x01),
+    /** カプセル。 */
+    CAPSULE(0x02),
+    ;
+
+    private static final String FAMILY_NAME =
+            "jp.sourceforge.mikutoga.pmd.resources.RigidShapeTypeName";
+
+    private final byte encoded;
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化int値
+     */
+    private RigidShapeType(int code){
+        this((byte)code);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param code 符号化byte値
+     */
+    private RigidShapeType(byte code){
+        this.encoded = code;
+        return;
+    }
+
+    /**
+     * byte値からデコードする。
+     * @param code byte値
+     * @return デコードされた列挙子。該当するものがなければnull
+     */
+    public static RigidShapeType decode(byte code){
+        RigidShapeType result = null;
+
+        for(RigidShapeType type : values()){
+            if(type.encode() == code){
+                result = type;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * byte値にエンコードする。
+     * @return byte値
+     */
+    public byte encode(){
+        return this.encoded;
+    }
+
+    /**
+     * デフォルトロケールでの表示名を返す。
+     * @return 表示名
+     */
+    public String getGuiName(){
+        Locale locale = Locale.getDefault();
+        return getGuiName(locale);
+    }
+
+    /**
+     * ロケールに準じた表示名を返す。
+     * @param locale ロケール。nullならデフォルトロケールと解釈される。
+     * @return 表示名
+     */
+    public String getGuiName(Locale locale){
+        if(locale == null) return getGuiName();
+        ResourceBundle rb = ResourceBundle.getBundle(FAMILY_NAME, locale);
+        String key = name();
+        String result = rb.getString(key);
+        return result;
+    }
+
+}
index 5970b0e..fba37e9 100644 (file)
-/*\r
- * shading information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * シェーディング情報。\r
- */\r
-public class ShadeInfo {\r
-\r
-    private ToonMap toonMap = new ToonMap();\r
-    private int toonIdx;\r
-\r
-    private String textureFileName = null;\r
-    private String spheremapFileName = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public ShadeInfo(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * トゥーンマップを設定する。\r
-     * @param map トゥーンマップ\r
-     */\r
-    public void setToonMap(ToonMap map){\r
-        this.toonMap = map;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * トゥーンマップを返す。\r
-     * @return トゥーンマップ\r
-     */\r
-    public ToonMap getToonMap(){\r
-        return this.toonMap;\r
-    }\r
-\r
-    /**\r
-     * トゥーンインデックスを設定する。\r
-     * @param idx トゥーンインデックス\r
-     */\r
-    public void setToonIndex(int idx){\r
-        this.toonIdx = idx;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * トゥーンインデックス値を返す。\r
-     * @return トゥーンインデックス値\r
-     */\r
-    public int getToonIndex(){\r
-        return this.toonIdx;\r
-    }\r
-\r
-    /**\r
-     * トゥーンインデックス値が有効か判定する。\r
-     * 現時点では0から9までの値を有効とする。\r
-     * @return 有効ならtrue\r
-     */\r
-    public boolean isValidToonIndex(){\r
-        if(0 <= this.toonIdx && this.toonIdx <= 9) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * トゥーンファイル名を返す。\r
-     * @return トゥーンファイル名\r
-     * @throws IllegalStateException トゥーンマップが設定されていない。\r
-     */\r
-    public String getToonFileName() throws IllegalStateException{\r
-        if(this.toonMap == null) throw new IllegalStateException();\r
-        String result = this.toonMap.getIndexedToon(this.toonIdx);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * テクスチャファイル名を設定する。\r
-     * @param fileName テクスチャファイル名\r
-     */\r
-    public void setTextureFileName(String fileName){\r
-        this.textureFileName = fileName;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * テクスチャファイル名を返す。\r
-     * @return テクスチャファイル名\r
-     */\r
-    public String getTextureFileName(){\r
-        return this.textureFileName;\r
-    }\r
-\r
-    /**\r
-     * スフィアマップファイル名を設定する。\r
-     * @param fileName スフィアマップファイル名\r
-     */\r
-    public void setSpheremapFileName(String fileName){\r
-        this.spheremapFileName = fileName;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * スフィアマップファイル名を返す。\r
-     * @return スフィアマップファイル名\r
-     */\r
-    public String getSpheremapFileName(){\r
-        return this.spheremapFileName;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("toon(")\r
-              .append(this.toonIdx)\r
-              .append(")=")\r
-              .append(getToonFileName())\r
-              .append(' ');\r
-        result.append("texture=")\r
-              .append(this.textureFileName)\r
-              .append(' ');\r
-        result.append("sphere=")\r
-              .append(this.spheremapFileName);\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * shading information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * シェーディング情報。
+ */
+public class ShadeInfo {
+
+    private ToonMap toonMap = new ToonMap();
+    private int toonIdx;
+
+    private String textureFileName = null;
+    private String spheremapFileName = null;
+
+    /**
+     * コンストラクタ。
+     */
+    public ShadeInfo(){
+        super();
+        return;
+    }
+
+    /**
+     * トゥーンマップを設定する。
+     * @param map トゥーンマップ
+     */
+    public void setToonMap(ToonMap map){
+        this.toonMap = map;
+        return;
+    }
+
+    /**
+     * トゥーンマップを返す。
+     * @return トゥーンマップ
+     */
+    public ToonMap getToonMap(){
+        return this.toonMap;
+    }
+
+    /**
+     * トゥーンインデックスを設定する。
+     * @param idx トゥーンインデックス
+     */
+    public void setToonIndex(int idx){
+        this.toonIdx = idx;
+        return;
+    }
+
+    /**
+     * トゥーンインデックス値を返す。
+     * @return トゥーンインデックス値
+     */
+    public int getToonIndex(){
+        return this.toonIdx;
+    }
+
+    /**
+     * トゥーンインデックス値が有効か判定する。
+     * 現時点では0から9までの値を有効とする。
+     * @return 有効ならtrue
+     */
+    public boolean isValidToonIndex(){
+        if(0 <= this.toonIdx && this.toonIdx <= 9) return true;
+        return false;
+    }
+
+    /**
+     * トゥーンファイル名を返す。
+     * @return トゥーンファイル名
+     * @throws IllegalStateException トゥーンマップが設定されていない。
+     */
+    public String getToonFileName() throws IllegalStateException{
+        if(this.toonMap == null) throw new IllegalStateException();
+        String result = this.toonMap.getIndexedToon(this.toonIdx);
+        return result;
+    }
+
+    /**
+     * テクスチャファイル名を設定する。
+     * @param fileName テクスチャファイル名
+     */
+    public void setTextureFileName(String fileName){
+        this.textureFileName = fileName;
+        return;
+    }
+
+    /**
+     * テクスチャファイル名を返す。
+     * @return テクスチャファイル名
+     */
+    public String getTextureFileName(){
+        return this.textureFileName;
+    }
+
+    /**
+     * スフィアマップファイル名を設定する。
+     * @param fileName スフィアマップファイル名
+     */
+    public void setSpheremapFileName(String fileName){
+        this.spheremapFileName = fileName;
+        return;
+    }
+
+    /**
+     * スフィアマップファイル名を返す。
+     * @return スフィアマップファイル名
+     */
+    public String getSpheremapFileName(){
+        return this.spheremapFileName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("toon(")
+              .append(this.toonIdx)
+              .append(")=")
+              .append(getToonFileName())
+              .append(' ');
+        result.append("texture=")
+              .append(this.textureFileName)
+              .append(' ');
+        result.append("sphere=")
+              .append(this.spheremapFileName);
+
+        return result.toString();
+    }
+
+}
index 5343d54..00c0444 100644 (file)
-/*\r
- * triangle surface\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * 3頂点の三角形からなる面情報。\r
- */\r
-public class Surface implements SerialNumbered, Iterable<Vertex> {\r
-\r
-    private Vertex vertex1;\r
-    private Vertex vertex2;\r
-    private Vertex vertex3;\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * 3頂点がnullの状態で生成される。\r
-     */\r
-    public Surface(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 3頂点を設定する。\r
-     * @param vertex1 頂点1\r
-     * @param vertex2 頂点2\r
-     * @param vertex3 頂点3\r
-     * @throws  IllegalArgumentException 重複する頂点が引数に含まれた\r
-     */\r
-    public void setTriangle(Vertex vertex1, Vertex vertex2, Vertex vertex3)\r
-            throws IllegalArgumentException{\r
-        if(vertex1 != null && (vertex1 == vertex2 || vertex1 == vertex3)){\r
-            throw new IllegalArgumentException();\r
-        }\r
-        if(vertex2 != null && vertex2 == vertex3){\r
-            throw new IllegalArgumentException();\r
-        }\r
-\r
-        this.vertex1 = vertex1;\r
-        this.vertex2 = vertex2;\r
-        this.vertex3 = vertex3;\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 3頂点を返す。\r
-     * @param store 頂点格納用配列。nullもしくは3要素に満たない場合は無視され、\r
-     * 新規に格納用配列が生成される。\r
-     * @return 先頭3要素に3頂点が収められた配列。未設定要素にはnullが入る。\r
-     * 引数が長さ3以上の配列であれば引数と同じ配列が返る。\r
-     */\r
-    public Vertex[] getTriangle(Vertex[] store){\r
-        Vertex[] result;\r
-        if(store == null || store.length < 3){\r
-            result = new Vertex[3];\r
-        }else{\r
-            result = store;\r
-        }\r
-\r
-        result[0] = this.vertex1;\r
-        result[1] = this.vertex2;\r
-        result[2] = this.vertex3;\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 頂点その1を返す。\r
-     * @return 頂点その1\r
-     */\r
-    public Vertex getVertex1(){\r
-        return this.vertex1;\r
-    }\r
-\r
-    /**\r
-     * 頂点その2を返す。\r
-     * @return 頂点その2\r
-     */\r
-    public Vertex getVertex2(){\r
-        return this.vertex2;\r
-    }\r
-\r
-    /**\r
-     * 頂点その3を返す。\r
-     * @return 頂点その3\r
-     */\r
-    public Vertex getVertex3(){\r
-        return this.vertex3;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * 頂点を返す反復子を生成する。\r
-     * 反復子がnullを返す可能性もありうる。\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public Iterator<Vertex> iterator(){\r
-        List<Vertex> list = new ArrayList<Vertex>(3);\r
-\r
-        list.add(this.vertex1);\r
-        list.add(this.vertex2);\r
-        list.add(this.vertex3);\r
-\r
-        return list.iterator();\r
-    }\r
-\r
-    /**\r
-     * 3頂点全てが設定されているか判定する。\r
-     * @return 3頂点とも非nullが設定されていればtrue\r
-     */\r
-    public boolean isCompleted(){\r
-        if(   this.vertex1 != null\r
-           && this.vertex2 != null\r
-           && this.vertex3 != null ){\r
-            return true;\r
-        }\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Surface(")\r
-              .append(getSerialNumber())\r
-              .append(")");\r
-\r
-        if(isCompleted()){\r
-            result.append(" VID=[")\r
-                  .append(this.vertex1.getSerialNumber())\r
-                  .append(',')\r
-                  .append(this.vertex2.getSerialNumber())\r
-                  .append(',')\r
-                  .append(this.vertex3.getSerialNumber())\r
-                  .append(']');\r
-        }\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * triangle surface
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * 3頂点の三角形からなる面情報。
+ */
+public class Surface implements SerialNumbered, Iterable<Vertex> {
+
+    private Vertex vertex1;
+    private Vertex vertex2;
+    private Vertex vertex3;
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     * 3頂点がnullの状態で生成される。
+     */
+    public Surface(){
+        super();
+        return;
+    }
+
+    /**
+     * 3頂点を設定する。
+     * @param vertex1 頂点1
+     * @param vertex2 頂点2
+     * @param vertex3 頂点3
+     * @throws  IllegalArgumentException 重複する頂点が引数に含まれた
+     */
+    public void setTriangle(Vertex vertex1, Vertex vertex2, Vertex vertex3)
+            throws IllegalArgumentException{
+        if(vertex1 != null && (vertex1 == vertex2 || vertex1 == vertex3)){
+            throw new IllegalArgumentException();
+        }
+        if(vertex2 != null && vertex2 == vertex3){
+            throw new IllegalArgumentException();
+        }
+
+        this.vertex1 = vertex1;
+        this.vertex2 = vertex2;
+        this.vertex3 = vertex3;
+
+        return;
+    }
+
+    /**
+     * 3頂点を返す。
+     * @param store 頂点格納用配列。nullもしくは3要素に満たない場合は無視され、
+     * 新規に格納用配列が生成される。
+     * @return 先頭3要素に3頂点が収められた配列。未設定要素にはnullが入る。
+     * 引数が長さ3以上の配列であれば引数と同じ配列が返る。
+     */
+    public Vertex[] getTriangle(Vertex[] store){
+        Vertex[] result;
+        if(store == null || store.length < 3){
+            result = new Vertex[3];
+        }else{
+            result = store;
+        }
+
+        result[0] = this.vertex1;
+        result[1] = this.vertex2;
+        result[2] = this.vertex3;
+
+        return result;
+    }
+
+    /**
+     * 頂点その1を返す。
+     * @return 頂点その1
+     */
+    public Vertex getVertex1(){
+        return this.vertex1;
+    }
+
+    /**
+     * 頂点その2を返す。
+     * @return 頂点その2
+     */
+    public Vertex getVertex2(){
+        return this.vertex2;
+    }
+
+    /**
+     * 頂点その3を返す。
+     * @return 頂点その3
+     */
+    public Vertex getVertex3(){
+        return this.vertex3;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 頂点を返す反復子を生成する。
+     * 反復子がnullを返す可能性もありうる。
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<Vertex> iterator(){
+        List<Vertex> list = new ArrayList<Vertex>(3);
+
+        list.add(this.vertex1);
+        list.add(this.vertex2);
+        list.add(this.vertex3);
+
+        return list.iterator();
+    }
+
+    /**
+     * 3頂点全てが設定されているか判定する。
+     * @return 3頂点とも非nullが設定されていればtrue
+     */
+    public boolean isCompleted(){
+        if(   this.vertex1 != null
+           && this.vertex2 != null
+           && this.vertex3 != null ){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Surface(")
+              .append(getSerialNumber())
+              .append(")");
+
+        if(isCompleted()){
+            result.append(" VID=[")
+                  .append(this.vertex1.getSerialNumber())
+                  .append(',')
+                  .append(this.vertex2.getSerialNumber())
+                  .append(',')
+                  .append(this.vertex3.getSerialNumber())
+                  .append(']');
+        }
+
+        return result.toString();
+    }
+
+}
index 153c0df..1a98d79 100644 (file)
-/*\r
- * toon file mapping\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Collections;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-/**\r
- * インデックス化されたトゥーンファイル構成。\r
- * 既存のトゥーンファイル構成と異なるトゥーンファイル名を用いることが可能。\r
- * <h1>デフォルトのトゥーンファイル構成。</h1>\r
- * <ul>\r
- * <li>0x00:toon01.bmp\r
- * <li>0x01:toon02.bmp\r
- * <li>.....\r
- * <li>0x09:toon10.bmp\r
- * <li>0xff:toon0.bmp\r
- * </ul>\r
- */\r
-public class ToonMap {\r
-\r
-    private static final Map<Integer, String> DEF_TOONMAP;\r
-\r
-    static{\r
-        Map<Integer, String> map = new TreeMap<Integer, String>();\r
-\r
-        map.put(0x00, "toon01.bmp");\r
-        map.put(0x01, "toon02.bmp");\r
-        map.put(0x02, "toon03.bmp");\r
-        map.put(0x03, "toon04.bmp");\r
-        map.put(0x04, "toon05.bmp");\r
-        map.put(0x05, "toon06.bmp");\r
-        map.put(0x06, "toon07.bmp");\r
-        map.put(0x07, "toon08.bmp");\r
-        map.put(0x08, "toon09.bmp");\r
-        map.put(0x09, "toon10.bmp");\r
-        map.put(0xff, "toon0.bmp");\r
-\r
-        DEF_TOONMAP = Collections.unmodifiableMap(map);\r
-    }\r
-\r
-    private final Map<Integer, String> toonMap =\r
-            new TreeMap<Integer, String>(DEF_TOONMAP);\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public ToonMap(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定したインデックス値に対応したトゥーンファイル名を返す。\r
-     * @param idx インデックス値\r
-     * @return トゥーンファイル名。該当するものがなければnull\r
-     */\r
-    public String getIndexedToon(int idx){\r
-        String result = this.toonMap.get(idx);\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 指定したインデックス値にトゥーンファイル名を設定する。\r
-     * @param idx インデックス値\r
-     * @param toonFileName トゥーンフィル名\r
-     * @throws NullPointerException トゥーンファイル名がnull\r
-     */\r
-    public void setIndexedToon(int idx, String toonFileName)\r
-            throws NullPointerException{\r
-        if(toonFileName == null) throw new NullPointerException();\r
-        this.toonMap.put(idx, toonFileName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * このトゥーンファイル構成がデフォルトのトゥーンファイル構成と等しいか判定する。\r
-     * @return 等しければtrue\r
-     */\r
-    public boolean isDefaultMap(){\r
-        if(this.toonMap.equals(DEF_TOONMAP)) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * 指定インデックスのトゥーンファイル名がデフォルトと等しいか判定する。\r
-     * @param idx インデックス\r
-     * @return デフォルトと等しければtrue。\r
-     */\r
-    public boolean isDefaultToon(int idx){\r
-        String thisToon = this.toonMap.get(idx);\r
-        if(thisToon == null) return false;\r
-\r
-        String defToon = DEF_TOONMAP.get(idx);\r
-        if(thisToon.equals(defToon)) return true;\r
-\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * このトゥーンファイル構成をデフォルト構成内容でリセットする。\r
-     */\r
-    public void resetDefaultMap(){\r
-        this.toonMap.clear();\r
-        this.toonMap.putAll(DEF_TOONMAP);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定インデックスのトゥーンファイル名をデフォルトのトゥーンファイル名にリセットする。\r
-     * @param idx インデックス値\r
-     */\r
-    public void resetIndexedToon(int idx){\r
-        String toonFile = DEF_TOONMAP.get(idx);\r
-        this.toonMap.put(idx, toonFile);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        boolean dumped = false;\r
-        for(Map.Entry<Integer, String> entry : this.toonMap.entrySet()){\r
-            Integer idx = entry.getKey();\r
-            String toonFile = entry.getValue();\r
-\r
-            if(dumped) result.append(", ");\r
-            result.append('(').append(idx).append(')');\r
-            result.append(toonFile);\r
-            dumped = true;\r
-        }\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * toon file mapping
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * インデックス化されたトゥーンファイル構成。
+ * 既存のトゥーンファイル構成と異なるトゥーンファイル名を用いることが可能。
+ * <h1>デフォルトのトゥーンファイル構成。</h1>
+ * <ul>
+ * <li>0x00:toon01.bmp
+ * <li>0x01:toon02.bmp
+ * <li>.....
+ * <li>0x09:toon10.bmp
+ * <li>0xff:toon0.bmp
+ * </ul>
+ */
+public class ToonMap {
+
+    private static final Map<Integer, String> DEF_TOONMAP;
+
+    static{
+        Map<Integer, String> map = new TreeMap<Integer, String>();
+
+        map.put(0x00, "toon01.bmp");
+        map.put(0x01, "toon02.bmp");
+        map.put(0x02, "toon03.bmp");
+        map.put(0x03, "toon04.bmp");
+        map.put(0x04, "toon05.bmp");
+        map.put(0x05, "toon06.bmp");
+        map.put(0x06, "toon07.bmp");
+        map.put(0x07, "toon08.bmp");
+        map.put(0x08, "toon09.bmp");
+        map.put(0x09, "toon10.bmp");
+        map.put(0xff, "toon0.bmp");
+
+        DEF_TOONMAP = Collections.unmodifiableMap(map);
+    }
+
+    private final Map<Integer, String> toonMap =
+            new TreeMap<Integer, String>(DEF_TOONMAP);
+
+    /**
+     * コンストラクタ。
+     */
+    public ToonMap(){
+        super();
+        return;
+    }
+
+    /**
+     * 指定したインデックス値に対応したトゥーンファイル名を返す。
+     * @param idx インデックス値
+     * @return トゥーンファイル名。該当するものがなければnull
+     */
+    public String getIndexedToon(int idx){
+        String result = this.toonMap.get(idx);
+        return result;
+    }
+
+    /**
+     * 指定したインデックス値にトゥーンファイル名を設定する。
+     * @param idx インデックス値
+     * @param toonFileName トゥーンフィル名
+     * @throws NullPointerException トゥーンファイル名がnull
+     */
+    public void setIndexedToon(int idx, String toonFileName)
+            throws NullPointerException{
+        if(toonFileName == null) throw new NullPointerException();
+        this.toonMap.put(idx, toonFileName);
+        return;
+    }
+
+    /**
+     * このトゥーンファイル構成がデフォルトのトゥーンファイル構成と等しいか判定する。
+     * @return 等しければtrue
+     */
+    public boolean isDefaultMap(){
+        if(this.toonMap.equals(DEF_TOONMAP)) return true;
+        return false;
+    }
+
+    /**
+     * 指定インデックスのトゥーンファイル名がデフォルトと等しいか判定する。
+     * @param idx インデックス
+     * @return デフォルトと等しければtrue。
+     */
+    public boolean isDefaultToon(int idx){
+        String thisToon = this.toonMap.get(idx);
+        if(thisToon == null) return false;
+
+        String defToon = DEF_TOONMAP.get(idx);
+        if(thisToon.equals(defToon)) return true;
+
+        return false;
+    }
+
+    /**
+     * このトゥーンファイル構成をデフォルト構成内容でリセットする。
+     */
+    public void resetDefaultMap(){
+        this.toonMap.clear();
+        this.toonMap.putAll(DEF_TOONMAP);
+        return;
+    }
+
+    /**
+     * 指定インデックスのトゥーンファイル名をデフォルトのトゥーンファイル名にリセットする。
+     * @param idx インデックス値
+     */
+    public void resetIndexedToon(int idx){
+        String toonFile = DEF_TOONMAP.get(idx);
+        this.toonMap.put(idx, toonFile);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        boolean dumped = false;
+        for(Map.Entry<Integer, String> entry : this.toonMap.entrySet()){
+            Integer idx = entry.getKey();
+            String toonFile = entry.getValue();
+
+            if(dumped) result.append(", ");
+            result.append('(').append(idx).append(')');
+            result.append(toonFile);
+            dumped = true;
+        }
+
+        return result.toString();
+    }
+
+}
index 6f61142..04aa853 100644 (file)
-/*\r
- * triplet-value range limitation\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * XYZ三組float値の範囲制約。\r
- */\r
-public class TripletRange {\r
-\r
-    private float xFrom;\r
-    private float xTo;\r
-    private float yFrom;\r
-    private float yTo;\r
-    private float zFrom;\r
-    private float zTo;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public TripletRange(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X値有効範囲を設定する。\r
-     * 下限値が上限値より大きければ入れ替える。\r
-     * @param xFrom X値下限\r
-     * @param xTo X値上限\r
-     */\r
-    public void setXRange(float xFrom, float xTo){\r
-        if(xFrom <= xTo){\r
-            this.xFrom = xFrom;\r
-            this.xTo = xTo;\r
-        }else{\r
-            this.xFrom = xTo;\r
-            this.xTo = xFrom;\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y値有効範囲を設定する。\r
-     * 下限値が上限値より大きければ入れ替える。\r
-     * @param yFrom Y値下限\r
-     * @param yTo Y値上限\r
-     */\r
-    public void setYRange(float yFrom, float yTo){\r
-        if(yFrom <= yTo){\r
-            this.yFrom = yFrom;\r
-            this.yTo = yTo;\r
-        }else{\r
-            this.yFrom = yTo;\r
-            this.yTo = yFrom;\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Z値有効範囲を設定する。\r
-     * 下限値が上限値より大きければ入れ替える。\r
-     * @param zFrom Z値下限\r
-     * @param zTo Z値上限\r
-     */\r
-    public void setZRange(float zFrom, float zTo){\r
-        if(zFrom <= zTo){\r
-            this.zFrom = zFrom;\r
-            this.zTo = zTo;\r
-        }else{\r
-            this.zFrom = zTo;\r
-            this.zTo = zFrom;\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X値下限を返す。\r
-     * @return X値下限\r
-     */\r
-    public float getXFrom(){\r
-        return this.xFrom;\r
-    }\r
-\r
-    /**\r
-     * X値上限を返す。\r
-     * @return X値上限\r
-     */\r
-    public float getXTo(){\r
-        return this.xTo;\r
-    }\r
-\r
-    /**\r
-     * Y値下限を返す。\r
-     * @return Y値下限\r
-     */\r
-    public float getYFrom(){\r
-        return this.yFrom;\r
-    }\r
-\r
-    /**\r
-     * Y値上限を返す。\r
-     * @return Y値上限\r
-     */\r
-    public float getYTo(){\r
-        return this.yTo;\r
-    }\r
-\r
-    /**\r
-     * Z値下限を返す。\r
-     * @return Z値下限\r
-     */\r
-    public float getZFrom(){\r
-        return this.zFrom;\r
-    }\r
-\r
-    /**\r
-     * Z値上限を返す。\r
-     * @return Z値上限\r
-     */\r
-    public float getZTo(){\r
-        return this.zTo;\r
-    }\r
-\r
-    /**\r
-     * X値が範囲制約を満たすか判定する。\r
-     * @param xVal X値\r
-     * @return 制約を満たすならtrue\r
-     */\r
-    public boolean isValidX(float xVal){\r
-        if(this.xFrom <= xVal && xVal <= this.xTo) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Y値が範囲制約を満たすか判定する。\r
-     * @param yVal Y値\r
-     * @return 制約を満たすならtrue\r
-     */\r
-    public boolean isValidY(float yVal){\r
-        if(this.yFrom <= yVal && yVal <= this.yTo) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Z値が範囲制約を満たすか判定する。\r
-     * @param zVal Z値\r
-     * @return 制約を満たすならtrue\r
-     */\r
-    public boolean isValidZ(float zVal){\r
-        if(this.zFrom <= zVal && zVal <= this.zTo) return true;\r
-        return false;\r
-    }\r
-\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("x=[")\r
-              .append(xFrom)\r
-              .append(" - ")\r
-              .append(xTo)\r
-              .append("] ");\r
-        result.append("y=[")\r
-              .append(yFrom)\r
-              .append(" - ")\r
-              .append(yTo)\r
-              .append("] ");\r
-        result.append("z=[")\r
-              .append(zFrom)\r
-              .append(" - ")\r
-              .append(zTo)\r
-              .append("]");\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * triplet-value range limitation
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * XYZ三組float値の範囲制約。
+ */
+public class TripletRange {
+
+    private float xFrom;
+    private float xTo;
+    private float yFrom;
+    private float yTo;
+    private float zFrom;
+    private float zTo;
+
+    /**
+     * コンストラクタ。
+     */
+    public TripletRange(){
+        super();
+        return;
+    }
+
+    /**
+     * X値有効範囲を設定する。
+     * 下限値が上限値より大きければ入れ替える。
+     * @param xFrom X値下限
+     * @param xTo X値上限
+     */
+    public void setXRange(float xFrom, float xTo){
+        if(xFrom <= xTo){
+            this.xFrom = xFrom;
+            this.xTo = xTo;
+        }else{
+            this.xFrom = xTo;
+            this.xTo = xFrom;
+        }
+        return;
+    }
+
+    /**
+     * Y値有効範囲を設定する。
+     * 下限値が上限値より大きければ入れ替える。
+     * @param yFrom Y値下限
+     * @param yTo Y値上限
+     */
+    public void setYRange(float yFrom, float yTo){
+        if(yFrom <= yTo){
+            this.yFrom = yFrom;
+            this.yTo = yTo;
+        }else{
+            this.yFrom = yTo;
+            this.yTo = yFrom;
+        }
+        return;
+    }
+
+    /**
+     * Z値有効範囲を設定する。
+     * 下限値が上限値より大きければ入れ替える。
+     * @param zFrom Z値下限
+     * @param zTo Z値上限
+     */
+    public void setZRange(float zFrom, float zTo){
+        if(zFrom <= zTo){
+            this.zFrom = zFrom;
+            this.zTo = zTo;
+        }else{
+            this.zFrom = zTo;
+            this.zTo = zFrom;
+        }
+        return;
+    }
+
+    /**
+     * X値下限を返す。
+     * @return X値下限
+     */
+    public float getXFrom(){
+        return this.xFrom;
+    }
+
+    /**
+     * X値上限を返す。
+     * @return X値上限
+     */
+    public float getXTo(){
+        return this.xTo;
+    }
+
+    /**
+     * Y値下限を返す。
+     * @return Y値下限
+     */
+    public float getYFrom(){
+        return this.yFrom;
+    }
+
+    /**
+     * Y値上限を返す。
+     * @return Y値上限
+     */
+    public float getYTo(){
+        return this.yTo;
+    }
+
+    /**
+     * Z値下限を返す。
+     * @return Z値下限
+     */
+    public float getZFrom(){
+        return this.zFrom;
+    }
+
+    /**
+     * Z値上限を返す。
+     * @return Z値上限
+     */
+    public float getZTo(){
+        return this.zTo;
+    }
+
+    /**
+     * X値が範囲制約を満たすか判定する。
+     * @param xVal X値
+     * @return 制約を満たすならtrue
+     */
+    public boolean isValidX(float xVal){
+        if(this.xFrom <= xVal && xVal <= this.xTo) return true;
+        return false;
+    }
+
+    /**
+     * Y値が範囲制約を満たすか判定する。
+     * @param yVal Y値
+     * @return 制約を満たすならtrue
+     */
+    public boolean isValidY(float yVal){
+        if(this.yFrom <= yVal && yVal <= this.yTo) return true;
+        return false;
+    }
+
+    /**
+     * Z値が範囲制約を満たすか判定する。
+     * @param zVal Z値
+     * @return 制約を満たすならtrue
+     */
+    public boolean isValidZ(float zVal){
+        if(this.zFrom <= zVal && zVal <= this.zTo) return true;
+        return false;
+    }
+
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("x=[")
+              .append(xFrom)
+              .append(" - ")
+              .append(xTo)
+              .append("] ");
+        result.append("y=[")
+              .append(yFrom)
+              .append(" - ")
+              .append(yTo)
+              .append("] ");
+        result.append("z=[")
+              .append(zFrom)
+              .append(" - ")
+              .append(zTo)
+              .append("]");
+
+        return result.toString();
+    }
+
+}
index ccbe2d3..9647c99 100644 (file)
@@ -1,94 +1,94 @@
-/*\r
- * 3D vector\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/**\r
- * XYZ三次元ベクトル。\r
- */\r
-public class Vec3d {\r
-\r
-    private float xVal;\r
-    private float yVal;\r
-    private float zVal;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public Vec3d(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X値を設定する。\r
-     * @param xVal X値\r
-     */\r
-    public void setXVal(float xVal){\r
-        this.xVal = xVal;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * X値を返す。\r
-     * @return X値\r
-     */\r
-    public float getXVal(){\r
-        return this.xVal;\r
-    }\r
-\r
-    /**\r
-     * Y値を設定する。\r
-     * @param yVal Y値\r
-     */\r
-    public void setYVal(float yVal){\r
-        this.yVal = yVal;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Y値を返す。\r
-     * @return Y値\r
-     */\r
-    public float getYVal(){\r
-        return this.yVal;\r
-    }\r
-\r
-    /**\r
-     * Z値を設定する。\r
-     * @param zVal Z値\r
-     */\r
-    public void setZVal(float zVal){\r
-        this.zVal = zVal;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Z値を返す。\r
-     * @return Z値\r
-     */\r
-    public float getZVal(){\r
-        return this.zVal;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("vec=[")\r
-              .append(this.xVal).append(", ")\r
-              .append(this.yVal).append(", ")\r
-              .append(this.zVal).append(']');\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 3D vector
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/**
+ * XYZ三次元ベクトル。
+ */
+public class Vec3d {
+
+    private float xVal;
+    private float yVal;
+    private float zVal;
+
+    /**
+     * コンストラクタ。
+     */
+    public Vec3d(){
+        super();
+        return;
+    }
+
+    /**
+     * X値を設定する。
+     * @param xVal X値
+     */
+    public void setXVal(float xVal){
+        this.xVal = xVal;
+        return;
+    }
+
+    /**
+     * X値を返す。
+     * @return X値
+     */
+    public float getXVal(){
+        return this.xVal;
+    }
+
+    /**
+     * Y値を設定する。
+     * @param yVal Y値
+     */
+    public void setYVal(float yVal){
+        this.yVal = yVal;
+        return;
+    }
+
+    /**
+     * Y値を返す。
+     * @return Y値
+     */
+    public float getYVal(){
+        return this.yVal;
+    }
+
+    /**
+     * Z値を設定する。
+     * @param zVal Z値
+     */
+    public void setZVal(float zVal){
+        this.zVal = zVal;
+        return;
+    }
+
+    /**
+     * Z値を返す。
+     * @return Z値
+     */
+    public float getZVal(){
+        return this.zVal;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("vec=[")
+              .append(this.xVal).append(", ")
+              .append(this.yVal).append(", ")
+              .append(this.zVal).append(']');
+
+        return result.toString();
+    }
+
+}
index 07789dd..cde99ec 100644 (file)
-/*\r
- * vertex information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-\r
-/**\r
- * 頂点情報。\r
- */\r
-public class Vertex implements SerialNumbered {\r
-\r
-    private static final int MIN_WEIGHT = 0;\r
-    private static final int MAX_WEIGHT = 100;\r
-\r
-    private final Pos3d position = new Pos3d();\r
-    private final Vec3d normal = new Vec3d();\r
-\r
-    private final Pos2d uvPosition = new Pos2d();\r
-\r
-    private BoneInfo boneA = null;\r
-    private BoneInfo boneB = null;\r
-\r
-    private int boneWeight = 50;\r
-\r
-    private boolean edgeAppearance = true;\r
-\r
-    private int serialNo = -1;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public Vertex(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 頂点位置座標を返す。\r
-     * @return 頂点の位置座標\r
-     */\r
-    public Pos3d getPosition(){\r
-        return this.position;\r
-    }\r
-\r
-    /**\r
-     * 法線ベクトルを返す。\r
-     * @return 法線ベクトル\r
-     */\r
-    public Vec3d getNormal(){\r
-        return this.normal;\r
-    }\r
-\r
-    /**\r
-     * UVマップ座標を返す。\r
-     * @return UVマップ情報\r
-     */\r
-    public Pos2d getUVPosition(){\r
-        return this.uvPosition;\r
-    }\r
-\r
-    /**\r
-     * 頂点の属するボーンを設定する。\r
-     * @param boneA ボーンA\r
-     * @param boneB ボーンB\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setBonePair(BoneInfo boneA, BoneInfo boneB)\r
-            throws NullPointerException{\r
-        if(boneA == null || boneB == null) throw new NullPointerException();\r
-        this.boneA = boneA;\r
-        this.boneB = boneB;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーンAを返す。\r
-     * @return ボーンA\r
-     */\r
-    public BoneInfo getBoneA(){\r
-        return this.boneA;\r
-    }\r
-\r
-    /**\r
-     * ボーンBを返す。\r
-     * @return ボーンB\r
-     */\r
-    public BoneInfo getBoneB(){\r
-        return this.boneB;\r
-    }\r
-\r
-    /**\r
-     * ボーンAのウェイト値を設定する。\r
-     * @param weight ウェイト値。0(影響小)-100(影響大)\r
-     * @throws IllegalArgumentException ウェイト値が範囲外\r
-     */\r
-    public void setWeightA(int weight) throws IllegalArgumentException{\r
-        if(   weight < MIN_WEIGHT\r
-           || MAX_WEIGHT < weight ){\r
-            throw new IllegalArgumentException();\r
-        }\r
-        this.boneWeight = weight;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーンBのウェイト値を設定する。\r
-     * @param weight ウェイト値。0(影響小)-100(影響大)\r
-     * @throws IllegalArgumentException ウェイト値が範囲外\r
-     */\r
-    public void setWeightB(int weight) throws IllegalArgumentException{\r
-        setWeightA(MAX_WEIGHT - weight);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーンAのウェイト値を返す。\r
-     * @return ウェイト値\r
-     */\r
-    public int getWeightA(){\r
-        return this.boneWeight;\r
-    }\r
-\r
-    /**\r
-     * ボーンBのウェイト値を返す。\r
-     * @return ウェイト値\r
-     */\r
-    public int getWeightB(){\r
-        int result = MAX_WEIGHT - this.boneWeight;\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * ボーンAのウェイト率を返す。\r
-     * @return ウェイト率。0.0(影響小)-1.0(影響大)\r
-     */\r
-    public float getWeightRatioA(){\r
-        return ((float)this.boneWeight) / (float)MAX_WEIGHT;\r
-    }\r
-\r
-    /**\r
-     * ボーンBのウェイト率を返す。\r
-     * @return ウェイト率。0.0(影響小)-1.0(影響大)\r
-     */\r
-    public float getWeightRatioB(){\r
-        return ((float)MAX_WEIGHT - (float)this.boneWeight)\r
-                / (float)MAX_WEIGHT;\r
-    }\r
-\r
-    /**\r
-     * エッジを表示するか設定する。\r
-     * マテリアル材質単位の設定より優先度は高い。\r
-     * @param show 表示するならtrue\r
-     */\r
-    public void setEdgeAppearance(boolean show){\r
-        this.edgeAppearance = show;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * エッジを表示するか判定する。\r
-     * マテリアル材質単位の設定より優先度は高い。\r
-     * @return 表示するならtrue\r
-     */\r
-    public boolean getEdgeAppearance(){\r
-        return this.edgeAppearance;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param num {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void setSerialNumber(int num){\r
-        this.serialNo = num;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public int getSerialNumber(){\r
-        return this.serialNo;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public String toString(){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        result.append("Vertex(").append(this.serialNo).append(") ");\r
-        result.append(this.position).append(' ');\r
-        result.append(this.normal).append(' ');\r
-        result.append("UV").append(this.uvPosition).append(' ');\r
-\r
-        result.append("[")\r
-              .append(this.boneA.getBoneName())\r
-              .append("<>")\r
-              .append(this.boneB.getBoneName())\r
-              .append("] ");\r
-\r
-        result.append("weight=").append(this.boneWeight).append(' ');\r
-\r
-        if(this.edgeAppearance) result.append("showEdge");\r
-        else                    result.append("hideEdge");\r
-\r
-        return result.toString();\r
-    }\r
-\r
-}\r
+/*
+ * vertex information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+
+/**
+ * 頂点情報。
+ */
+public class Vertex implements SerialNumbered {
+
+    private static final int MIN_WEIGHT = 0;
+    private static final int MAX_WEIGHT = 100;
+
+    private final Pos3d position = new Pos3d();
+    private final Vec3d normal = new Vec3d();
+
+    private final Pos2d uvPosition = new Pos2d();
+
+    private BoneInfo boneA = null;
+    private BoneInfo boneB = null;
+
+    private int boneWeight = 50;
+
+    private boolean edgeAppearance = true;
+
+    private int serialNo = -1;
+
+    /**
+     * コンストラクタ。
+     */
+    public Vertex(){
+        super();
+        return;
+    }
+
+    /**
+     * 頂点位置座標を返す。
+     * @return 頂点の位置座標
+     */
+    public Pos3d getPosition(){
+        return this.position;
+    }
+
+    /**
+     * 法線ベクトルを返す。
+     * @return 法線ベクトル
+     */
+    public Vec3d getNormal(){
+        return this.normal;
+    }
+
+    /**
+     * UVマップ座標を返す。
+     * @return UVマップ情報
+     */
+    public Pos2d getUVPosition(){
+        return this.uvPosition;
+    }
+
+    /**
+     * 頂点の属するボーンを設定する。
+     * @param boneA ボーンA
+     * @param boneB ボーンB
+     * @throws NullPointerException 引数がnull
+     */
+    public void setBonePair(BoneInfo boneA, BoneInfo boneB)
+            throws NullPointerException{
+        if(boneA == null || boneB == null) throw new NullPointerException();
+        this.boneA = boneA;
+        this.boneB = boneB;
+        return;
+    }
+
+    /**
+     * ボーンAを返す。
+     * @return ボーンA
+     */
+    public BoneInfo getBoneA(){
+        return this.boneA;
+    }
+
+    /**
+     * ボーンBを返す。
+     * @return ボーンB
+     */
+    public BoneInfo getBoneB(){
+        return this.boneB;
+    }
+
+    /**
+     * ボーンAのウェイト値を設定する。
+     * @param weight ウェイト値。0(影響小)-100(影響大)
+     * @throws IllegalArgumentException ウェイト値が範囲外
+     */
+    public void setWeightA(int weight) throws IllegalArgumentException{
+        if(   weight < MIN_WEIGHT
+           || MAX_WEIGHT < weight ){
+            throw new IllegalArgumentException();
+        }
+        this.boneWeight = weight;
+        return;
+    }
+
+    /**
+     * ボーンBのウェイト値を設定する。
+     * @param weight ウェイト値。0(影響小)-100(影響大)
+     * @throws IllegalArgumentException ウェイト値が範囲外
+     */
+    public void setWeightB(int weight) throws IllegalArgumentException{
+        setWeightA(MAX_WEIGHT - weight);
+        return;
+    }
+
+    /**
+     * ボーンAのウェイト値を返す。
+     * @return ウェイト値
+     */
+    public int getWeightA(){
+        return this.boneWeight;
+    }
+
+    /**
+     * ボーンBのウェイト値を返す。
+     * @return ウェイト値
+     */
+    public int getWeightB(){
+        int result = MAX_WEIGHT - this.boneWeight;
+        return result;
+    }
+
+    /**
+     * ボーンAのウェイト率を返す。
+     * @return ウェイト率。0.0(影響小)-1.0(影響大)
+     */
+    public float getWeightRatioA(){
+        return ((float)this.boneWeight) / (float)MAX_WEIGHT;
+    }
+
+    /**
+     * ボーンBのウェイト率を返す。
+     * @return ウェイト率。0.0(影響小)-1.0(影響大)
+     */
+    public float getWeightRatioB(){
+        return ((float)MAX_WEIGHT - (float)this.boneWeight)
+                / (float)MAX_WEIGHT;
+    }
+
+    /**
+     * エッジを表示するか設定する。
+     * マテリアル材質単位の設定より優先度は高い。
+     * @param show 表示するならtrue
+     */
+    public void setEdgeAppearance(boolean show){
+        this.edgeAppearance = show;
+        return;
+    }
+
+    /**
+     * エッジを表示するか判定する。
+     * マテリアル材質単位の設定より優先度は高い。
+     * @return 表示するならtrue
+     */
+    public boolean getEdgeAppearance(){
+        return this.edgeAppearance;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param num {@inheritDoc}
+     */
+    @Override
+    public void setSerialNumber(int num){
+        this.serialNo = num;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getSerialNumber(){
+        return this.serialNo;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String toString(){
+        StringBuilder result = new StringBuilder();
+
+        result.append("Vertex(").append(this.serialNo).append(") ");
+        result.append(this.position).append(' ');
+        result.append(this.normal).append(' ');
+        result.append("UV").append(this.uvPosition).append(' ');
+
+        result.append("[")
+              .append(this.boneA.getBoneName())
+              .append("<>")
+              .append(this.boneB.getBoneName())
+              .append("] ");
+
+        result.append("weight=").append(this.boneWeight).append(' ');
+
+        if(this.edgeAppearance) result.append("showEdge");
+        else                    result.append("hideEdge");
+
+        return result.toString();
+    }
+
+}
index 4be99ed..106c9b8 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * PMDモデルファイルに相当するオブジェクト各種。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * PMDモデルファイルに相当するオブジェクト各種。
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+/* EOF */
index 45c463b..dcff552 100644 (file)
-/*\r
- * abstract exporter\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.nio.BufferOverflowException;\r
-import java.nio.ByteBuffer;\r
-import java.nio.ByteOrder;\r
-import java.nio.CharBuffer;\r
-import java.nio.charset.Charset;\r
-import java.nio.charset.CharsetEncoder;\r
-import java.nio.charset.CoderResult;\r
-import java.nio.charset.CodingErrorAction;\r
-\r
-/**\r
- * 抽象化されたエクスポーター共通部。\r
- */\r
-public abstract class AbstractExporter {\r
-\r
-    private static final Charset CS_WIN31J = Charset.forName("windows-31j");\r
-\r
-    private static final String ERRMSG_TOOLONGTEXT = "too long text";\r
-    private static final String ERRMSG_INVUCSSEQ = "invalid unicode sequence";\r
-    private static final String ERRMSG_NONWIN31J = "no character in win31j";\r
-\r
-    private static final int BYTES_SHORT = Short  .SIZE / Byte.SIZE;\r
-    private static final int BYTES_INT   = Integer.SIZE / Byte.SIZE;\r
-    private static final int BYTES_FLOAT = Float  .SIZE / Byte.SIZE;\r
-\r
-    private static final int BUFSZ_BYTE = 512;\r
-    private static final int BUFSZ_CHAR = 512;\r
-\r
-    private final OutputStream ostream;\r
-\r
-    private final byte[] barray;\r
-    private final ByteBuffer bbuf;\r
-\r
-    private final CharBuffer cbuf;\r
-    private final CharsetEncoder encoder;\r
-\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    protected AbstractExporter(OutputStream stream)\r
-            throws NullPointerException{\r
-        super();\r
-\r
-        if(stream == null) throw new NullPointerException();\r
-        this.ostream = stream;\r
-\r
-        this.barray = new byte[BUFSZ_BYTE];\r
-        this.bbuf = ByteBuffer.wrap(this.barray);\r
-        this.bbuf.order(ByteOrder.LITTLE_ENDIAN);\r
-\r
-        this.cbuf = CharBuffer.allocate(BUFSZ_CHAR);\r
-        this.encoder = CS_WIN31J.newEncoder();\r
-        this.encoder.onMalformedInput(CodingErrorAction.REPORT);\r
-        this.encoder.onUnmappableCharacter(CodingErrorAction.REPORT);\r
-        this.encoder.reset();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 出力をフラッシュする。\r
-     * I/O効率とデバッグ効率のバランスを考え、ご利用は計画的に。\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void flush() throws IOException{\r
-        this.ostream.flush();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * byte値を出力する。\r
-     * @param bVal byte値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpByte(byte bVal) throws IOException{\r
-        this.ostream.write((int)bVal);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * int値をbyte値で出力する。\r
-     * byte値に収まらない上位ビットはそのまま捨てられる。\r
-     * @param iVal int値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpByte(int iVal) throws IOException{\r
-        dumpByte((byte)iVal);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * short値を出力する。\r
-     * @param sVal short値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpShort(short sVal) throws IOException{\r
-        this.bbuf.clear();\r
-        this.bbuf.putShort(sVal);\r
-        this.ostream.write(this.barray, 0, BYTES_SHORT);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * int値をshort値で出力する。\r
-     * short値に収まらない上位ビットはそのまま捨てられる。\r
-     * @param iVal int値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpShort(int iVal) throws IOException{\r
-        dumpShort((short)iVal);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * int値を出力する。\r
-     * @param iVal int値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpInt(int iVal) throws IOException{\r
-        this.bbuf.clear();\r
-        this.bbuf.putInt(iVal);\r
-        this.ostream.write(this.barray, 0, BYTES_INT);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * float値を出力する。\r
-     * @param fVal float値\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpFloat(float fVal) throws IOException{\r
-        this.bbuf.clear();\r
-        this.bbuf.putFloat(fVal);\r
-        this.ostream.write(this.barray, 0, BYTES_FLOAT);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 文字列をwindows-31jエンコーディングで出力する。\r
-     * @param seq 文字列\r
-     * @return 出力されたbyte総数。\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字エンコーディングに関するエラー\r
-     */\r
-    protected int dumpCharSequence(CharSequence seq)\r
-            throws IOException, IllegalPmdTextException{\r
-        encodeToByteBuffer(seq);\r
-        this.bbuf.flip();\r
-        int length = dumpByteBuffer();\r
-        return length;\r
-    }\r
-\r
-    /**\r
-     * windows-31jにエンコーディングした文字列を内部バッファに蓄積する。\r
-     * @param seq 文字列\r
-     * @throws IllegalPmdTextException 文字エンコーディングに関するエラー。\r
-     * 考えられる状況としては、\r
-     * <ul>\r
-     * <li>入力文字列がUnicodeとしてすでにおかしい。\r
-     * (サロゲートペアがペアになってないなど)\r
-     * <li>windows-31jにない文字をエンコーディングしようとした\r
-     * <li>エンコーディング結果が内部バッファに収まらなかった。\r
-     * </ul>\r
-     * など。\r
-     */\r
-    private void encodeToByteBuffer(CharSequence seq)\r
-            throws IllegalPmdTextException{\r
-        this.cbuf.clear();\r
-        try{\r
-            this.cbuf.append(seq);\r
-        }catch(BufferOverflowException e){\r
-            throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);\r
-        }\r
-        this.cbuf.flip();\r
-\r
-        this.bbuf.clear();\r
-\r
-        CoderResult result = this.encoder.encode(this.cbuf, this.bbuf, true);\r
-        if( ! result.isUnderflow()){\r
-            if(result.isOverflow()){\r
-                throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);\r
-            }else if(result.isMalformed()){\r
-                throw new IllegalPmdTextException(ERRMSG_INVUCSSEQ);\r
-            }else if(result.isUnmappable()){\r
-                throw new IllegalPmdTextException(ERRMSG_NONWIN31J);\r
-            }else{\r
-                assert false;\r
-                throw new AssertionError();\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 内部バッファに蓄積されたbyte値並びを出力する。\r
-     * @return 出力されたbyte数\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private int dumpByteBuffer() throws IOException{\r
-        int offset = this.bbuf.position();\r
-        int limit = this.bbuf.limit();\r
-        int length = limit - offset;\r
-        this.ostream.write(this.barray, offset, length);\r
-\r
-        this.bbuf.position(limit);\r
-\r
-        return length;\r
-    }\r
-\r
-}\r
+/*
+ * abstract exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * 抽象化されたエクスポーター共通部。
+ */
+public abstract class AbstractExporter {
+
+    private static final Charset CS_WIN31J = Charset.forName("windows-31j");
+
+    private static final String ERRMSG_TOOLONGTEXT = "too long text";
+    private static final String ERRMSG_INVUCSSEQ = "invalid unicode sequence";
+    private static final String ERRMSG_NONWIN31J = "no character in win31j";
+
+    private static final int BYTES_SHORT = Short  .SIZE / Byte.SIZE;
+    private static final int BYTES_INT   = Integer.SIZE / Byte.SIZE;
+    private static final int BYTES_FLOAT = Float  .SIZE / Byte.SIZE;
+
+    private static final int BUFSZ_BYTE = 512;
+    private static final int BUFSZ_CHAR = 512;
+
+    private final OutputStream ostream;
+
+    private final byte[] barray;
+    private final ByteBuffer bbuf;
+
+    private final CharBuffer cbuf;
+    private final CharsetEncoder encoder;
+
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    protected AbstractExporter(OutputStream stream)
+            throws NullPointerException{
+        super();
+
+        if(stream == null) throw new NullPointerException();
+        this.ostream = stream;
+
+        this.barray = new byte[BUFSZ_BYTE];
+        this.bbuf = ByteBuffer.wrap(this.barray);
+        this.bbuf.order(ByteOrder.LITTLE_ENDIAN);
+
+        this.cbuf = CharBuffer.allocate(BUFSZ_CHAR);
+        this.encoder = CS_WIN31J.newEncoder();
+        this.encoder.onMalformedInput(CodingErrorAction.REPORT);
+        this.encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        this.encoder.reset();
+
+        return;
+    }
+
+    /**
+     * 出力をフラッシュする。
+     * I/O効率とデバッグ効率のバランスを考え、ご利用は計画的に。
+     * @throws IOException 出力エラー
+     */
+    protected void flush() throws IOException{
+        this.ostream.flush();
+        return;
+    }
+
+    /**
+     * byte値を出力する。
+     * @param bVal byte値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpByte(byte bVal) throws IOException{
+        this.ostream.write((int)bVal);
+        return;
+    }
+
+    /**
+     * int値をbyte値で出力する。
+     * byte値に収まらない上位ビットはそのまま捨てられる。
+     * @param iVal int値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpByte(int iVal) throws IOException{
+        dumpByte((byte)iVal);
+        return;
+    }
+
+    /**
+     * short値を出力する。
+     * @param sVal short値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpShort(short sVal) throws IOException{
+        this.bbuf.clear();
+        this.bbuf.putShort(sVal);
+        this.ostream.write(this.barray, 0, BYTES_SHORT);
+        return;
+    }
+
+    /**
+     * int値をshort値で出力する。
+     * short値に収まらない上位ビットはそのまま捨てられる。
+     * @param iVal int値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpShort(int iVal) throws IOException{
+        dumpShort((short)iVal);
+        return;
+    }
+
+    /**
+     * int値を出力する。
+     * @param iVal int値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpInt(int iVal) throws IOException{
+        this.bbuf.clear();
+        this.bbuf.putInt(iVal);
+        this.ostream.write(this.barray, 0, BYTES_INT);
+        return;
+    }
+
+    /**
+     * float値を出力する。
+     * @param fVal float値
+     * @throws IOException 出力エラー
+     */
+    protected void dumpFloat(float fVal) throws IOException{
+        this.bbuf.clear();
+        this.bbuf.putFloat(fVal);
+        this.ostream.write(this.barray, 0, BYTES_FLOAT);
+        return;
+    }
+
+    /**
+     * 文字列をwindows-31jエンコーディングで出力する。
+     * @param seq 文字列
+     * @return 出力されたbyte総数。
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字エンコーディングに関するエラー
+     */
+    protected int dumpCharSequence(CharSequence seq)
+            throws IOException, IllegalPmdTextException{
+        encodeToByteBuffer(seq);
+        this.bbuf.flip();
+        int length = dumpByteBuffer();
+        return length;
+    }
+
+    /**
+     * windows-31jにエンコーディングした文字列を内部バッファに蓄積する。
+     * @param seq 文字列
+     * @throws IllegalPmdTextException 文字エンコーディングに関するエラー。
+     * 考えられる状況としては、
+     * <ul>
+     * <li>入力文字列がUnicodeとしてすでにおかしい。
+     * (サロゲートペアがペアになってないなど)
+     * <li>windows-31jにない文字をエンコーディングしようとした
+     * <li>エンコーディング結果が内部バッファに収まらなかった。
+     * </ul>
+     * など。
+     */
+    private void encodeToByteBuffer(CharSequence seq)
+            throws IllegalPmdTextException{
+        this.cbuf.clear();
+        try{
+            this.cbuf.append(seq);
+        }catch(BufferOverflowException e){
+            throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);
+        }
+        this.cbuf.flip();
+
+        this.bbuf.clear();
+
+        CoderResult result = this.encoder.encode(this.cbuf, this.bbuf, true);
+        if( ! result.isUnderflow()){
+            if(result.isOverflow()){
+                throw new IllegalPmdTextException(ERRMSG_TOOLONGTEXT);
+            }else if(result.isMalformed()){
+                throw new IllegalPmdTextException(ERRMSG_INVUCSSEQ);
+            }else if(result.isUnmappable()){
+                throw new IllegalPmdTextException(ERRMSG_NONWIN31J);
+            }else{
+                assert false;
+                throw new AssertionError();
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * 内部バッファに蓄積されたbyte値並びを出力する。
+     * @return 出力されたbyte数
+     * @throws IOException 出力エラー
+     */
+    private int dumpByteBuffer() throws IOException{
+        int offset = this.bbuf.position();
+        int limit = this.bbuf.limit();
+        int length = limit - offset;
+        this.ostream.write(this.barray, offset, length);
+
+        this.bbuf.position(limit);
+
+        return length;
+    }
+
+}
index 3dfed28..6beb293 100644 (file)
@@ -1,33 +1,33 @@
-/*\r
- * illegal model exception\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-/**\r
- * モデルデータの不備を発見した場合の例外。\r
- */\r
-@SuppressWarnings("serial")\r
-public class IllegalPmdException extends Exception{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public IllegalPmdException(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message メッセージ\r
-     */\r
-    public IllegalPmdException(String message){\r
-        super(message);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * illegal model exception
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+/**
+ * モデルデータの不備を発見した場合の例外。
+ */
+@SuppressWarnings("serial")
+public class IllegalPmdException extends Exception{
+
+    /**
+     * コンストラクタ。
+     */
+    public IllegalPmdException(){
+        super();
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message メッセージ
+     */
+    public IllegalPmdException(String message){
+        super(message);
+        return;
+    }
+
+}
index 6ab1dbe..fdb3d46 100644 (file)
@@ -1,41 +1,41 @@
-/*\r
- * illegal text in model exception\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-/**\r
- * 不正なテキスト情報をモデルデータ中に発見した場合の例外。\r
- * <p>\r
- * 考えられる理由としては\r
- * <ul>\r
- * <li>用意されたフォーマットに対し文字列が長すぎる。\r
- * <li>文字エンコーディングできない文字が含まれている\r
- * <li>ユニコード文字列として既に変。\r
- * </ul>\r
- * など。\r
- */\r
-@SuppressWarnings("serial")\r
-public class IllegalPmdTextException extends IllegalPmdException{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public IllegalPmdTextException(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message メッセージ\r
-     */\r
-    public IllegalPmdTextException(String message){\r
-        super(message);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * illegal text in model exception
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+/**
+ * 不正なテキスト情報をモデルデータ中に発見した場合の例外。
+ * <p>
+ * 考えられる理由としては
+ * <ul>
+ * <li>用意されたフォーマットに対し文字列が長すぎる。
+ * <li>文字エンコーディングできない文字が含まれている
+ * <li>ユニコード文字列として既に変。
+ * </ul>
+ * など。
+ */
+@SuppressWarnings("serial")
+public class IllegalPmdTextException extends IllegalPmdException{
+
+    /**
+     * コンストラクタ。
+     */
+    public IllegalPmdTextException(){
+        super();
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message メッセージ
+     */
+    public IllegalPmdTextException(String message){
+        super(message);
+        return;
+    }
+
+}
index 7d11ed3..c08946f 100644 (file)
@@ -1,30 +1,30 @@
-/*\r
- * model exporter for pmd-file(up to date)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.io.OutputStream;\r
-\r
-/**\r
- * 最新仕様のPMDファイルエクスポーター。\r
- * 将来のリリースにおいて、\r
- * 常に最新のPMDモデルファイルフォーマットに対応したエクスポーターの\r
- * 別名であることが保証される。つもり。\r
- */\r
-public class PmdExporter extends PmdExporterExt3{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public PmdExporter(OutputStream stream) throws NullPointerException{\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * model exporter for pmd-file(up to date)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.io.OutputStream;
+
+/**
+ * 最新仕様のPMDファイルエクスポーター。
+ * 将来のリリースにおいて、
+ * 常に最新のPMDモデルファイルフォーマットに対応したエクスポーターの
+ * 別名であることが保証される。つもり。
+ */
+public class PmdExporter extends PmdExporterExt3{
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    public PmdExporter(OutputStream stream) throws NullPointerException{
+        super(stream);
+        return;
+    }
+
+}
index d8866eb..3b1c342 100644 (file)
-/*\r
- * model exporter for pmd-file\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.awt.Color;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.util.Collections;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.BoneType;\r
-import jp.sourceforge.mikutoga.pmd.IKChain;\r
-import jp.sourceforge.mikutoga.pmd.Material;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.MorphType;\r
-import jp.sourceforge.mikutoga.pmd.MorphVertex;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos2d;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.ShadeInfo;\r
-import jp.sourceforge.mikutoga.pmd.Surface;\r
-import jp.sourceforge.mikutoga.pmd.Vec3d;\r
-import jp.sourceforge.mikutoga.pmd.Vertex;\r
-\r
-/**\r
- * PMDファイルのエクスポーター(拡張無し基本フォーマット)。\r
- * <p>\r
- * 英名対応以降のPMDファイルフォーマットを\r
- * 使いたくない場合はこのエクスポーターを用いて出力せよ。\r
- */\r
-public class PmdExporterBase extends AbstractExporter{\r
-\r
-    /** 前(親)ボーンが無い場合の便宜的なボーンID。 */\r
-    public static final int NOPREVBONE_ID = 0xffff;\r
-    /** 次(子)ボーンが無い場合の便宜的なボーンID。 */\r
-    public static final int NONEXTBONE_ID = 0x0000;\r
-    /** 影響元IKボーンが無い場合の便宜的なボーンID。 */\r
-    public static final int NOIKBONE_ID = 0x0000;\r
-\r
-    private static final String MAGIC = "Pmd";\r
-\r
-    private static final byte[] NULLFILLER =\r
-        { (byte)0x00 };\r
-    private static final byte[] FDFILLER =\r
-        { (byte)0x00, (byte)0xfd };\r
-    private static final byte[] LFFILLER =\r
-        { (byte)0x0a, (byte)0x00, (byte)0xfd };\r
-\r
-    /** 改行文字列 CR。 */\r
-    private static final String CR = "\r";       // 0x0d\r
-    /** 改行文字列 LF。 */\r
-    private static final String LF = "\n";       // 0x0a\r
-    /** 改行文字列 CRLF。 */\r
-    private static final String CRLF = CR + LF;  // 0x0d, 0x0a\r
-\r
-    static{\r
-        assert NOPREVBONE_ID > PmdLimits.MAX_BONE - 1;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public PmdExporterBase(OutputStream stream)\r
-            throws NullPointerException{\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 改行文字の正規化を行う。\r
-     * CR(0x0d)およびCRLF(0x0d0a)がLF(0x0a)へと正規化される。\r
-     * @param text 文字列\r
-     * @return 正規化の行われた文字列。\r
-     */\r
-    protected static String normalizeBreak(String text){\r
-        String result = text;\r
-\r
-        result = result.replace(CRLF, LF);\r
-        result = result.replace(CR, LF);\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 文字列を指定されたバイト長で出力する。\r
-     * 文字列の改行記号はLF(0x0a)に正規化される。\r
-     * エンコード結果がバイト長に満たない場合は\r
-     * 1つの0x00及びそれに続く複数の0xfdがパディングされる。\r
-     * @param text 文字列\r
-     * @param maxByteLength バイト長指定\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException エンコード結果が\r
-     * 指定バイト長をはみ出した。\r
-     */\r
-    protected void dumpText(String text, int maxByteLength)\r
-            throws IOException, IllegalPmdTextException{\r
-        dumpText(text, maxByteLength, FDFILLER);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 文字列を指定されたバイト長で出力する。\r
-     * 文字列の改行記号はLF(0x0a)に正規化される。\r
-     * エンコード結果がバイト長に満たない場合は\r
-     * fillerがパディングされる。\r
-     * @param text 文字列\r
-     * @param maxByteLength バイト超指定\r
-     * @param filler 出力結果が足りない場合の詰め物。\r
-     * それでも足りない場合は最後のbyte要素が繰り返し出力される。\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException エンコード結果が\r
-     * 指定バイト長をはみ出した\r
-     */\r
-    protected void dumpText(String text, int maxByteLength, byte[] filler)\r
-            throws IOException, IllegalPmdTextException{\r
-        String normalized = normalizeBreak(text);\r
-        int blen = dumpCharSequence(normalized);\r
-        int remain = maxByteLength - blen;\r
-\r
-        if(remain < 0) throw new IllegalPmdTextException("too long text");\r
-\r
-        int fillerIdx = 0;\r
-        while(remain > 0){\r
-            if(fillerIdx >= filler.length){\r
-                fillerIdx = filler.length - 1;\r
-            }\r
-            dumpByte(filler[fillerIdx]);\r
-            fillerIdx++;\r
-            remain--;\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モデルデータをPMDファイル形式で出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdException モデルデータに不備が発見された\r
-     */\r
-    public void dumpPmdModel(PmdModel model)\r
-            throws IOException, IllegalPmdException{\r
-        dumpBasic(model);\r
-        dumpVertexList(model);\r
-        dumpSurfaceList(model);\r
-        dumpMaterialList(model);\r
-        dumpBoneList(model);\r
-        dumpIKChainList(model);\r
-        dumpMorphList(model);\r
-        dumpMorphGroup(model);\r
-        dumpBoneGroupList(model);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モデル基本情報を出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException モデル名もしくは説明が長すぎる\r
-     */\r
-    private void dumpBasic(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        dumpCharSequence(MAGIC);\r
-        float ver = model.getHeaderVersion();\r
-        dumpFloat(ver);\r
-\r
-        String modelName   = model.getModelName()  .getPrimaryText();\r
-        String description = model.getDescription().getPrimaryText();\r
-\r
-        dumpText(modelName, PmdLimits.MAXBYTES_MODELNAME);\r
-        dumpText(description, PmdLimits.MAXBYTES_MODELDESC);\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 頂点リストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpVertexList(PmdModel model)\r
-            throws IOException{\r
-        List<Vertex> vList = model.getVertexList();\r
-\r
-        int vertexNum = vList.size();\r
-        dumpInt(vertexNum);\r
-\r
-        for(Vertex vertex : vList){\r
-            dumpVertex(vertex);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 個別の頂点データを出力する。\r
-     * @param vertex 頂点\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpVertex(Vertex vertex)\r
-            throws IOException{\r
-        Pos3d position = vertex.getPosition();\r
-        dumpPos3d(position);\r
-\r
-        Vec3d normal = vertex.getNormal();\r
-        dumpVec3d(normal);\r
-\r
-        Pos2d uv = vertex.getUVPosition();\r
-        dumpPos2d(uv);\r
-\r
-        BoneInfo boneA = vertex.getBoneA();\r
-        BoneInfo boneB = vertex.getBoneB();\r
-        dumpSerialIdAsShort(boneA);\r
-        dumpSerialIdAsShort(boneB);\r
-\r
-        int weight = vertex.getWeightA();\r
-        dumpByte((byte)weight);\r
-\r
-        byte edgeFlag;\r
-        boolean hasEdge = vertex.getEdgeAppearance();\r
-        if(hasEdge) edgeFlag = 0x00;\r
-        else        edgeFlag = 0x01;\r
-        dumpByte(edgeFlag);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 面リストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpSurfaceList(PmdModel model)\r
-            throws IOException{\r
-        int surfaceNum = 0;\r
-        List<Material> materialList = model.getMaterialList();\r
-        for(Material material : materialList){\r
-            surfaceNum += material.getSurfaceList().size();\r
-        }\r
-        dumpInt(surfaceNum * 3);\r
-\r
-        Vertex[] triangle = new Vertex[3];\r
-        for(Material material : materialList){\r
-            for(Surface surface : material){\r
-                surface.getTriangle(triangle);\r
-                dumpShort(triangle[0].getSerialNumber());\r
-                dumpShort(triangle[1].getSerialNumber());\r
-                dumpShort(triangle[2].getSerialNumber());\r
-            }\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * マテリアル素材リストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException シェーディングファイル情報が長すぎる\r
-     */\r
-    private void dumpMaterialList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        List<Material> materialList = model.getMaterialList();\r
-\r
-        int materialNum = materialList.size();\r
-        dumpInt(materialNum);\r
-\r
-        float[] rgba = new float[4];\r
-\r
-        for(Material material : materialList){\r
-            Color diffuse = material.getDiffuseColor();\r
-            diffuse.getRGBComponents(rgba);\r
-            dumpFloat(rgba[0]);\r
-            dumpFloat(rgba[1]);\r
-            dumpFloat(rgba[2]);\r
-            dumpFloat(rgba[3]);\r
-\r
-            float shininess = material.getShininess();\r
-            dumpFloat(shininess);\r
-\r
-            Color specular = material.getSpecularColor();\r
-            specular.getRGBComponents(rgba);\r
-            dumpFloat(rgba[0]);\r
-            dumpFloat(rgba[1]);\r
-            dumpFloat(rgba[2]);\r
-\r
-            Color ambient = material.getAmbientColor();\r
-            ambient.getRGBComponents(rgba);\r
-            dumpFloat(rgba[0]);\r
-            dumpFloat(rgba[1]);\r
-            dumpFloat(rgba[2]);\r
-\r
-            ShadeInfo shade = material.getShadeInfo();\r
-            int toonIdx = shade.getToonIndex();\r
-            dumpByte(toonIdx);\r
-\r
-            byte edgeFlag;\r
-            boolean showEdge = material.getEdgeAppearance();\r
-            if(showEdge) edgeFlag = 0x01;\r
-            else         edgeFlag = 0x00;\r
-            dumpByte(edgeFlag);\r
-\r
-            int surfaceNum = material.getSurfaceList().size();\r
-            dumpInt(surfaceNum * 3);\r
-\r
-            dumpShadeFileInfo(shade);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * シェーディングファイル情報を出力する。\r
-     * @param shade シェーディング情報\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException ファイル名が長すぎる\r
-     */\r
-    private void dumpShadeFileInfo(ShadeInfo shade)\r
-            throws IOException, IllegalPmdTextException{\r
-        String textureFile   = shade.getTextureFileName();\r
-        String spheremapFile = shade.getSpheremapFileName();\r
-\r
-        StringBuilder text = new StringBuilder();\r
-        if(textureFile != null) text.append(textureFile);\r
-        if(spheremapFile != null && spheremapFile.length() > 0){\r
-            text.append('*')\r
-                  .append(spheremapFile);\r
-        }\r
-\r
-        byte[] filler;\r
-        if(text.length() <= 0) filler = NULLFILLER;\r
-        else                   filler = FDFILLER;\r
-\r
-        dumpText(text.toString(),\r
-                 PmdLimits.MAXBYTES_TEXTUREFILENAME,\r
-                 filler );\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーンリストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException ボーン名が長すぎる\r
-     */\r
-    private void dumpBoneList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        List<BoneInfo> boneList = model.getBoneList();\r
-\r
-        int boneNum = boneList.size();\r
-        dumpShort(boneNum);\r
-\r
-        for(BoneInfo bone : boneList){\r
-            dumpBone(bone);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 個別のボーン情報を出力する。\r
-     * @param bone ボーン情報\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException ボーン名が長すぎる\r
-     */\r
-    private void dumpBone(BoneInfo bone)\r
-            throws IOException, IllegalPmdTextException{\r
-        String boneName = bone.getBoneName().getPrimaryText();\r
-        dumpText(boneName, PmdLimits.MAXBYTES_BONENAME);\r
-\r
-        BoneInfo prev = bone.getPrevBone();\r
-        if(prev != null) dumpSerialIdAsShort(prev);\r
-        else             dumpShort(NOPREVBONE_ID);\r
-\r
-        BoneInfo next = bone.getNextBone();\r
-        if(next != null) dumpSerialIdAsShort(next);\r
-        else             dumpShort(NONEXTBONE_ID);\r
-\r
-        BoneType type = bone.getBoneType();\r
-        dumpByte(type.encode());\r
-\r
-        if(type == BoneType.LINKEDROT){\r
-            int ratio = bone.getRotationRatio();\r
-            dumpShort(ratio);\r
-        }else{\r
-            BoneInfo ik = bone.getIKBone();\r
-            if(ik != null) dumpSerialIdAsShort(ik);\r
-            else           dumpShort(NOIKBONE_ID);\r
-        }\r
-\r
-        Pos3d position = bone.getPosition();\r
-        dumpPos3d(position);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKチェーンリストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpIKChainList(PmdModel model)\r
-            throws IOException{\r
-        List<IKChain> ikChainList = model.getIKChainList();\r
-\r
-        int ikNum = ikChainList.size();\r
-        dumpShort(ikNum);\r
-\r
-        for(IKChain chain : ikChainList){\r
-            dumpIKChain(chain);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * IKチェーンを出力する。\r
-     * @param chain IKチェーン\r
-     * @throws IOException 出力エラー\r
-     */\r
-    // TODO ボーンリストから自動抽出できる情報ではないのか?\r
-    private void dumpIKChain(IKChain chain)\r
-            throws IOException{\r
-        BoneInfo ikBone = chain.getIkBone();\r
-        dumpSerialIdAsShort(ikBone);\r
-\r
-        List<BoneInfo> boneList = chain.getChainedBoneList();\r
-\r
-        BoneInfo bone1st = boneList.get(0);\r
-        dumpSerialIdAsShort(bone1st);\r
-\r
-        int boneNum = boneList.size();\r
-        dumpByte(boneNum - 1);\r
-\r
-        int depth = chain.getIKDepth();\r
-        float weight = chain.getIKWeight();\r
-\r
-        dumpShort(depth);\r
-        dumpFloat(weight);\r
-\r
-        for(int idx = 1; idx < boneNum; idx++){ // リストの2番目以降全て\r
-            BoneInfo bone = boneList.get(idx);\r
-            dumpSerialIdAsShort(bone);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフリストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException モーフ名が長すぎる\r
-     */\r
-    private void dumpMorphList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();\r
-        Set<MorphType> typeSet = morphMap.keySet();\r
-        List<MorphVertex> mergedMorphVertexList = model.mergeMorphVertex();\r
-\r
-        int totalMorphPart = 0;\r
-        for(MorphType type : typeSet){\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            totalMorphPart += partList.size();\r
-        }\r
-\r
-        if(totalMorphPart <= 0){\r
-            dumpShort(0);\r
-            return;\r
-        }else{\r
-            totalMorphPart++;  // baseの分\r
-            dumpShort(totalMorphPart);\r
-        }\r
-\r
-        dumpText("base", PmdLimits.MAXBYTES_MORPHNAME);\r
-        int totalVertex = mergedMorphVertexList.size();\r
-        dumpInt(totalVertex);\r
-        dumpByte(MorphType.BASE.encode());\r
-        for(MorphVertex morphVertex : mergedMorphVertexList){\r
-            Vertex baseVertex = morphVertex.getBaseVertex();\r
-            dumpInt(baseVertex.getSerialNumber());\r
-            dumpPos3d(baseVertex.getPosition());\r
-        }\r
-\r
-        for(MorphType type : typeSet){\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                dumpText(part.getMorphName().getPrimaryText(),\r
-                         PmdLimits.MAXBYTES_MORPHNAME );\r
-                List<MorphVertex> morphVertexList = part.getMorphVertexList();\r
-                dumpInt(morphVertexList.size());\r
-                dumpByte(part.getMorphType().encode());\r
-\r
-                for(MorphVertex morphVertex : morphVertexList){\r
-                    dumpInt(morphVertex.getSerialNumber());\r
-                    dumpPos3d(morphVertex.getOffset());\r
-                }\r
-            }\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モーフグループを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpMorphGroup(PmdModel model)\r
-            throws IOException{\r
-        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();\r
-        Set<MorphType> typeSet = morphMap.keySet();\r
-\r
-        int totalMorph = 0;\r
-        for(MorphType type : typeSet){\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            totalMorph += partList.size();\r
-        }\r
-        dumpByte(totalMorph);\r
-\r
-        List<MorphType> typeList = new LinkedList<MorphType>();\r
-        for(MorphType type : typeSet){\r
-            assert ! type.isBase();\r
-            typeList.add(type);\r
-        }\r
-        Collections.reverse(typeList);  // 一応本家と互換性を\r
-\r
-        for(MorphType type : typeList){\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                dumpSerialIdAsShort(part);\r
-            }\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーングループリストを出力する。\r
-     * デフォルトボーングループ内訳は出力されない。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException ボーングループ名が長すぎる\r
-     */\r
-    private void dumpBoneGroupList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        List<BoneGroup> groupList = model.getBoneGroupList();\r
-        int groupNum = groupList.size();\r
-        dumpByte(groupNum - 1);\r
-\r
-        int dispBoneNum = 0;\r
-        for(BoneGroup group : groupList){\r
-            if(group.isDefaultBoneGroup()) continue;\r
-            dumpText(group.getGroupName().getPrimaryText(),\r
-                     PmdLimits.MAXBYTES_BONEGROUPNAME, LFFILLER );\r
-            dispBoneNum += group.getBoneList().size();\r
-        }\r
-        dumpInt(dispBoneNum);\r
-\r
-        for(BoneGroup group : groupList){\r
-            if(group.isDefaultBoneGroup()) continue;\r
-            for(BoneInfo bone : group){\r
-                dumpSerialIdAsShort(bone);\r
-                int groupId = group.getSerialNumber();\r
-                dumpByte(groupId);\r
-            }\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 各種通し番号をshort値で出力する。\r
-     * short値に収まらない上位ビットは捨てられる。\r
-     * @param obj 番号づけられたオブジェクト\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpSerialIdAsShort(SerialNumbered obj)\r
-            throws IOException{\r
-        int serialId = obj.getSerialNumber();\r
-        dumpShort(serialId);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 2次元位置情報を出力する。\r
-     * @param position 2次元位置情報\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpPos2d(Pos2d position) throws IOException{\r
-        float xPos = position.getXPos();\r
-        float yPos = position.getYPos();\r
-\r
-        dumpFloat(xPos);\r
-        dumpFloat(yPos);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 3次元位置情報を出力する。\r
-     * @param position 3次元位置情報\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpPos3d(Pos3d position) throws IOException{\r
-        float xPos = position.getXPos();\r
-        float yPos = position.getYPos();\r
-        float zPos = position.getZPos();\r
-\r
-        dumpFloat(xPos);\r
-        dumpFloat(yPos);\r
-        dumpFloat(zPos);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 3次元ベクトル情報を出力する。\r
-     * @param vector 3次元ベクトル\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpVec3d(Vec3d vector) throws IOException{\r
-        float xVal = vector.getXVal();\r
-        float yVal = vector.getYVal();\r
-        float zVal = vector.getZVal();\r
-\r
-        dumpFloat(xVal);\r
-        dumpFloat(yVal);\r
-        dumpFloat(zVal);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * model exporter for pmd-file
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.BoneType;
+import jp.sourceforge.mikutoga.pmd.IKChain;
+import jp.sourceforge.mikutoga.pmd.Material;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.MorphType;
+import jp.sourceforge.mikutoga.pmd.MorphVertex;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos2d;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.ShadeInfo;
+import jp.sourceforge.mikutoga.pmd.Surface;
+import jp.sourceforge.mikutoga.pmd.Vec3d;
+import jp.sourceforge.mikutoga.pmd.Vertex;
+
+/**
+ * PMDファイルのエクスポーター(拡張無し基本フォーマット)。
+ * <p>
+ * 英名対応以降のPMDファイルフォーマットを
+ * 使いたくない場合はこのエクスポーターを用いて出力せよ。
+ */
+public class PmdExporterBase extends AbstractExporter{
+
+    /** 前(親)ボーンが無い場合の便宜的なボーンID。 */
+    public static final int NOPREVBONE_ID = 0xffff;
+    /** 次(子)ボーンが無い場合の便宜的なボーンID。 */
+    public static final int NONEXTBONE_ID = 0x0000;
+    /** 影響元IKボーンが無い場合の便宜的なボーンID。 */
+    public static final int NOIKBONE_ID = 0x0000;
+
+    private static final String MAGIC = "Pmd";
+
+    private static final byte[] NULLFILLER =
+        { (byte)0x00 };
+    private static final byte[] FDFILLER =
+        { (byte)0x00, (byte)0xfd };
+    private static final byte[] LFFILLER =
+        { (byte)0x0a, (byte)0x00, (byte)0xfd };
+
+    /** 改行文字列 CR。 */
+    private static final String CR = "\r";       // 0x0d
+    /** 改行文字列 LF。 */
+    private static final String LF = "\n";       // 0x0a
+    /** 改行文字列 CRLF。 */
+    private static final String CRLF = CR + LF;  // 0x0d, 0x0a
+
+    static{
+        assert NOPREVBONE_ID > PmdLimits.MAX_BONE - 1;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    public PmdExporterBase(OutputStream stream)
+            throws NullPointerException{
+        super(stream);
+        return;
+    }
+
+    /**
+     * 改行文字の正規化を行う。
+     * CR(0x0d)およびCRLF(0x0d0a)がLF(0x0a)へと正規化される。
+     * @param text 文字列
+     * @return 正規化の行われた文字列。
+     */
+    protected static String normalizeBreak(String text){
+        String result = text;
+
+        result = result.replace(CRLF, LF);
+        result = result.replace(CR, LF);
+
+        return result;
+    }
+
+    /**
+     * 文字列を指定されたバイト長で出力する。
+     * 文字列の改行記号はLF(0x0a)に正規化される。
+     * エンコード結果がバイト長に満たない場合は
+     * 1つの0x00及びそれに続く複数の0xfdがパディングされる。
+     * @param text 文字列
+     * @param maxByteLength バイト長指定
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException エンコード結果が
+     * 指定バイト長をはみ出した。
+     */
+    protected void dumpText(String text, int maxByteLength)
+            throws IOException, IllegalPmdTextException{
+        dumpText(text, maxByteLength, FDFILLER);
+        return;
+    }
+
+    /**
+     * 文字列を指定されたバイト長で出力する。
+     * 文字列の改行記号はLF(0x0a)に正規化される。
+     * エンコード結果がバイト長に満たない場合は
+     * fillerがパディングされる。
+     * @param text 文字列
+     * @param maxByteLength バイト超指定
+     * @param filler 出力結果が足りない場合の詰め物。
+     * それでも足りない場合は最後のbyte要素が繰り返し出力される。
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException エンコード結果が
+     * 指定バイト長をはみ出した
+     */
+    protected void dumpText(String text, int maxByteLength, byte[] filler)
+            throws IOException, IllegalPmdTextException{
+        String normalized = normalizeBreak(text);
+        int blen = dumpCharSequence(normalized);
+        int remain = maxByteLength - blen;
+
+        if(remain < 0) throw new IllegalPmdTextException("too long text");
+
+        int fillerIdx = 0;
+        while(remain > 0){
+            if(fillerIdx >= filler.length){
+                fillerIdx = filler.length - 1;
+            }
+            dumpByte(filler[fillerIdx]);
+            fillerIdx++;
+            remain--;
+        }
+
+        return;
+    }
+
+    /**
+     * モデルデータをPMDファイル形式で出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdException モデルデータに不備が発見された
+     */
+    public void dumpPmdModel(PmdModel model)
+            throws IOException, IllegalPmdException{
+        dumpBasic(model);
+        dumpVertexList(model);
+        dumpSurfaceList(model);
+        dumpMaterialList(model);
+        dumpBoneList(model);
+        dumpIKChainList(model);
+        dumpMorphList(model);
+        dumpMorphGroup(model);
+        dumpBoneGroupList(model);
+
+        return;
+    }
+
+    /**
+     * モデル基本情報を出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException モデル名もしくは説明が長すぎる
+     */
+    private void dumpBasic(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        dumpCharSequence(MAGIC);
+        float ver = model.getHeaderVersion();
+        dumpFloat(ver);
+
+        String modelName   = model.getModelName()  .getPrimaryText();
+        String description = model.getDescription().getPrimaryText();
+
+        dumpText(modelName, PmdLimits.MAXBYTES_MODELNAME);
+        dumpText(description, PmdLimits.MAXBYTES_MODELDESC);
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 頂点リストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     */
+    private void dumpVertexList(PmdModel model)
+            throws IOException{
+        List<Vertex> vList = model.getVertexList();
+
+        int vertexNum = vList.size();
+        dumpInt(vertexNum);
+
+        for(Vertex vertex : vList){
+            dumpVertex(vertex);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 個別の頂点データを出力する。
+     * @param vertex 頂点
+     * @throws IOException 出力エラー
+     */
+    private void dumpVertex(Vertex vertex)
+            throws IOException{
+        Pos3d position = vertex.getPosition();
+        dumpPos3d(position);
+
+        Vec3d normal = vertex.getNormal();
+        dumpVec3d(normal);
+
+        Pos2d uv = vertex.getUVPosition();
+        dumpPos2d(uv);
+
+        BoneInfo boneA = vertex.getBoneA();
+        BoneInfo boneB = vertex.getBoneB();
+        dumpSerialIdAsShort(boneA);
+        dumpSerialIdAsShort(boneB);
+
+        int weight = vertex.getWeightA();
+        dumpByte((byte)weight);
+
+        byte edgeFlag;
+        boolean hasEdge = vertex.getEdgeAppearance();
+        if(hasEdge) edgeFlag = 0x00;
+        else        edgeFlag = 0x01;
+        dumpByte(edgeFlag);
+
+        return;
+    }
+
+    /**
+     * 面リストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     */
+    private void dumpSurfaceList(PmdModel model)
+            throws IOException{
+        int surfaceNum = 0;
+        List<Material> materialList = model.getMaterialList();
+        for(Material material : materialList){
+            surfaceNum += material.getSurfaceList().size();
+        }
+        dumpInt(surfaceNum * 3);
+
+        Vertex[] triangle = new Vertex[3];
+        for(Material material : materialList){
+            for(Surface surface : material){
+                surface.getTriangle(triangle);
+                dumpShort(triangle[0].getSerialNumber());
+                dumpShort(triangle[1].getSerialNumber());
+                dumpShort(triangle[2].getSerialNumber());
+            }
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * マテリアル素材リストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException シェーディングファイル情報が長すぎる
+     */
+    private void dumpMaterialList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        List<Material> materialList = model.getMaterialList();
+
+        int materialNum = materialList.size();
+        dumpInt(materialNum);
+
+        float[] rgba = new float[4];
+
+        for(Material material : materialList){
+            Color diffuse = material.getDiffuseColor();
+            diffuse.getRGBComponents(rgba);
+            dumpFloat(rgba[0]);
+            dumpFloat(rgba[1]);
+            dumpFloat(rgba[2]);
+            dumpFloat(rgba[3]);
+
+            float shininess = material.getShininess();
+            dumpFloat(shininess);
+
+            Color specular = material.getSpecularColor();
+            specular.getRGBComponents(rgba);
+            dumpFloat(rgba[0]);
+            dumpFloat(rgba[1]);
+            dumpFloat(rgba[2]);
+
+            Color ambient = material.getAmbientColor();
+            ambient.getRGBComponents(rgba);
+            dumpFloat(rgba[0]);
+            dumpFloat(rgba[1]);
+            dumpFloat(rgba[2]);
+
+            ShadeInfo shade = material.getShadeInfo();
+            int toonIdx = shade.getToonIndex();
+            dumpByte(toonIdx);
+
+            byte edgeFlag;
+            boolean showEdge = material.getEdgeAppearance();
+            if(showEdge) edgeFlag = 0x01;
+            else         edgeFlag = 0x00;
+            dumpByte(edgeFlag);
+
+            int surfaceNum = material.getSurfaceList().size();
+            dumpInt(surfaceNum * 3);
+
+            dumpShadeFileInfo(shade);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * シェーディングファイル情報を出力する。
+     * @param shade シェーディング情報
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException ファイル名が長すぎる
+     */
+    private void dumpShadeFileInfo(ShadeInfo shade)
+            throws IOException, IllegalPmdTextException{
+        String textureFile   = shade.getTextureFileName();
+        String spheremapFile = shade.getSpheremapFileName();
+
+        StringBuilder text = new StringBuilder();
+        if(textureFile != null) text.append(textureFile);
+        if(spheremapFile != null && spheremapFile.length() > 0){
+            text.append('*')
+                  .append(spheremapFile);
+        }
+
+        byte[] filler;
+        if(text.length() <= 0) filler = NULLFILLER;
+        else                   filler = FDFILLER;
+
+        dumpText(text.toString(),
+                 PmdLimits.MAXBYTES_TEXTUREFILENAME,
+                 filler );
+
+        return;
+    }
+
+    /**
+     * ボーンリストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException ボーン名が長すぎる
+     */
+    private void dumpBoneList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        List<BoneInfo> boneList = model.getBoneList();
+
+        int boneNum = boneList.size();
+        dumpShort(boneNum);
+
+        for(BoneInfo bone : boneList){
+            dumpBone(bone);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 個別のボーン情報を出力する。
+     * @param bone ボーン情報
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException ボーン名が長すぎる
+     */
+    private void dumpBone(BoneInfo bone)
+            throws IOException, IllegalPmdTextException{
+        String boneName = bone.getBoneName().getPrimaryText();
+        dumpText(boneName, PmdLimits.MAXBYTES_BONENAME);
+
+        BoneInfo prev = bone.getPrevBone();
+        if(prev != null) dumpSerialIdAsShort(prev);
+        else             dumpShort(NOPREVBONE_ID);
+
+        BoneInfo next = bone.getNextBone();
+        if(next != null) dumpSerialIdAsShort(next);
+        else             dumpShort(NONEXTBONE_ID);
+
+        BoneType type = bone.getBoneType();
+        dumpByte(type.encode());
+
+        if(type == BoneType.LINKEDROT){
+            int ratio = bone.getRotationRatio();
+            dumpShort(ratio);
+        }else{
+            BoneInfo ik = bone.getIKBone();
+            if(ik != null) dumpSerialIdAsShort(ik);
+            else           dumpShort(NOIKBONE_ID);
+        }
+
+        Pos3d position = bone.getPosition();
+        dumpPos3d(position);
+
+        return;
+    }
+
+    /**
+     * IKチェーンリストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     */
+    private void dumpIKChainList(PmdModel model)
+            throws IOException{
+        List<IKChain> ikChainList = model.getIKChainList();
+
+        int ikNum = ikChainList.size();
+        dumpShort(ikNum);
+
+        for(IKChain chain : ikChainList){
+            dumpIKChain(chain);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * IKチェーンを出力する。
+     * @param chain IKチェーン
+     * @throws IOException 出力エラー
+     */
+    // TODO ボーンリストから自動抽出できる情報ではないのか?
+    private void dumpIKChain(IKChain chain)
+            throws IOException{
+        BoneInfo ikBone = chain.getIkBone();
+        dumpSerialIdAsShort(ikBone);
+
+        List<BoneInfo> boneList = chain.getChainedBoneList();
+
+        BoneInfo bone1st = boneList.get(0);
+        dumpSerialIdAsShort(bone1st);
+
+        int boneNum = boneList.size();
+        dumpByte(boneNum - 1);
+
+        int depth = chain.getIKDepth();
+        float weight = chain.getIKWeight();
+
+        dumpShort(depth);
+        dumpFloat(weight);
+
+        for(int idx = 1; idx < boneNum; idx++){ // リストの2番目以降全て
+            BoneInfo bone = boneList.get(idx);
+            dumpSerialIdAsShort(bone);
+        }
+
+        return;
+    }
+
+    /**
+     * モーフリストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException モーフ名が長すぎる
+     */
+    private void dumpMorphList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
+        Set<MorphType> typeSet = morphMap.keySet();
+        List<MorphVertex> mergedMorphVertexList = model.mergeMorphVertex();
+
+        int totalMorphPart = 0;
+        for(MorphType type : typeSet){
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            totalMorphPart += partList.size();
+        }
+
+        if(totalMorphPart <= 0){
+            dumpShort(0);
+            return;
+        }else{
+            totalMorphPart++;  // baseの分
+            dumpShort(totalMorphPart);
+        }
+
+        dumpText("base", PmdLimits.MAXBYTES_MORPHNAME);
+        int totalVertex = mergedMorphVertexList.size();
+        dumpInt(totalVertex);
+        dumpByte(MorphType.BASE.encode());
+        for(MorphVertex morphVertex : mergedMorphVertexList){
+            Vertex baseVertex = morphVertex.getBaseVertex();
+            dumpInt(baseVertex.getSerialNumber());
+            dumpPos3d(baseVertex.getPosition());
+        }
+
+        for(MorphType type : typeSet){
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                dumpText(part.getMorphName().getPrimaryText(),
+                         PmdLimits.MAXBYTES_MORPHNAME );
+                List<MorphVertex> morphVertexList = part.getMorphVertexList();
+                dumpInt(morphVertexList.size());
+                dumpByte(part.getMorphType().encode());
+
+                for(MorphVertex morphVertex : morphVertexList){
+                    dumpInt(morphVertex.getSerialNumber());
+                    dumpPos3d(morphVertex.getOffset());
+                }
+            }
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * モーフグループを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     */
+    private void dumpMorphGroup(PmdModel model)
+            throws IOException{
+        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
+        Set<MorphType> typeSet = morphMap.keySet();
+
+        int totalMorph = 0;
+        for(MorphType type : typeSet){
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            totalMorph += partList.size();
+        }
+        dumpByte(totalMorph);
+
+        List<MorphType> typeList = new LinkedList<MorphType>();
+        for(MorphType type : typeSet){
+            assert ! type.isBase();
+            typeList.add(type);
+        }
+        Collections.reverse(typeList);  // 一応本家と互換性を
+
+        for(MorphType type : typeList){
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                dumpSerialIdAsShort(part);
+            }
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * ボーングループリストを出力する。
+     * デフォルトボーングループ内訳は出力されない。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException ボーングループ名が長すぎる
+     */
+    private void dumpBoneGroupList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        List<BoneGroup> groupList = model.getBoneGroupList();
+        int groupNum = groupList.size();
+        dumpByte(groupNum - 1);
+
+        int dispBoneNum = 0;
+        for(BoneGroup group : groupList){
+            if(group.isDefaultBoneGroup()) continue;
+            dumpText(group.getGroupName().getPrimaryText(),
+                     PmdLimits.MAXBYTES_BONEGROUPNAME, LFFILLER );
+            dispBoneNum += group.getBoneList().size();
+        }
+        dumpInt(dispBoneNum);
+
+        for(BoneGroup group : groupList){
+            if(group.isDefaultBoneGroup()) continue;
+            for(BoneInfo bone : group){
+                dumpSerialIdAsShort(bone);
+                int groupId = group.getSerialNumber();
+                dumpByte(groupId);
+            }
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 各種通し番号をshort値で出力する。
+     * short値に収まらない上位ビットは捨てられる。
+     * @param obj 番号づけられたオブジェクト
+     * @throws IOException 出力エラー
+     */
+    protected void dumpSerialIdAsShort(SerialNumbered obj)
+            throws IOException{
+        int serialId = obj.getSerialNumber();
+        dumpShort(serialId);
+        return;
+    }
+
+    /**
+     * 2次元位置情報を出力する。
+     * @param position 2次元位置情報
+     * @throws IOException 出力エラー
+     */
+    protected void dumpPos2d(Pos2d position) throws IOException{
+        float xPos = position.getXPos();
+        float yPos = position.getYPos();
+
+        dumpFloat(xPos);
+        dumpFloat(yPos);
+
+        return;
+    }
+
+    /**
+     * 3次元位置情報を出力する。
+     * @param position 3次元位置情報
+     * @throws IOException 出力エラー
+     */
+    protected void dumpPos3d(Pos3d position) throws IOException{
+        float xPos = position.getXPos();
+        float yPos = position.getYPos();
+        float zPos = position.getZPos();
+
+        dumpFloat(xPos);
+        dumpFloat(yPos);
+        dumpFloat(zPos);
+
+        return;
+    }
+
+    /**
+     * 3次元ベクトル情報を出力する。
+     * @param vector 3次元ベクトル
+     * @throws IOException 出力エラー
+     */
+    protected void dumpVec3d(Vec3d vector) throws IOException{
+        float xVal = vector.getXVal();
+        float yVal = vector.getYVal();
+        float zVal = vector.getZVal();
+
+        dumpFloat(xVal);
+        dumpFloat(yVal);
+        dumpFloat(zVal);
+
+        return;
+    }
+
+}
index 73b1919..2516a50 100644 (file)
-/*\r
- * model exporter for pmd-file(Ext1)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.util.List;\r
-import java.util.Map;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.MorphType;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-\r
-/**\r
- * PMDファイルのエクスポーター(拡張1:英名対応)。\r
- * <p>\r
- * 任意のトゥーンファイル名対応以降のPMDファイルフォーマットを\r
- * 使いたくない場合はこのエクスポーターを用いて出力せよ。\r
- */\r
-public class PmdExporterExt1 extends PmdExporterBase{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public PmdExporterExt1(OutputStream stream)\r
-            throws NullPointerException{\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param model {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws IllegalPmdException {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void dumpPmdModel(PmdModel model)\r
-            throws IOException, IllegalPmdException{\r
-        super.dumpPmdModel(model);\r
-\r
-        dumpGlobalInfo(model);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 英語名情報を出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字列が長すぎる。\r
-     */\r
-    private void dumpGlobalInfo(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        boolean hasGlobal = model.hasGlobalText();\r
-        byte globalFlag;\r
-        if(hasGlobal) globalFlag = 0x01;\r
-        else          globalFlag = 0x00;\r
-        dumpByte(globalFlag);\r
-\r
-        if(hasGlobal){\r
-            dumpBasicGlobal(model);\r
-            dumpBoneGlobal(model);\r
-            dumpMorphGlobal(model);\r
-            dumpBoneGroupGlobal(model);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モデル基本情報を英語で出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字列が長すぎる。\r
-     */\r
-    private void dumpBasicGlobal(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        String modelName = model.getModelName().getGlobalText();\r
-        if(modelName == null) modelName = "";\r
-        dumpText(modelName, PmdLimits.MAXBYTES_MODELNAME);\r
-\r
-        String description = model.getDescription().getGlobalText();\r
-        if(description == null) description = "";\r
-        dumpText(description, PmdLimits.MAXBYTES_MODELDESC);\r
-\r
-        flush();\r
-    }\r
-\r
-    /**\r
-     * ボーン英語名情報を出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字列が長すぎる。\r
-     */\r
-    private void dumpBoneGlobal(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        for(BoneInfo bone : model.getBoneList()){\r
-            String boneName = bone.getBoneName().getGlobalText();\r
-            if(boneName == null) boneName = "";\r
-            dumpText(boneName, PmdLimits.MAXBYTES_BONENAME);\r
-        }\r
-\r
-        flush();\r
-    }\r
-\r
-    /**\r
-     * モーフ英語名情報を出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字列が長すぎる。\r
-     */\r
-    private void dumpMorphGlobal(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();\r
-\r
-        for(MorphType type : MorphType.values()){\r
-            if(type.isBase()) continue;\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                String morphName = part.getMorphName().getGlobalText();\r
-                if(morphName == null) morphName = "";\r
-                dumpText(morphName, PmdLimits.MAXBYTES_MORPHNAME);\r
-            }\r
-        }\r
-\r
-        flush();\r
-    }\r
-\r
-    /**\r
-     * ボーングループ英語名情報を出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 文字列が長すぎる\r
-     */\r
-    private void dumpBoneGroupGlobal(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        for(BoneGroup group : model.getBoneGroupList()){\r
-            if(group.isDefaultBoneGroup()) continue;\r
-            String groupName = group.getGroupName().getGlobalText();\r
-            if(groupName == null) groupName = "";\r
-            dumpText(groupName, PmdLimits.MAXBYTES_BONEGROUPNAME);\r
-        }\r
-\r
-        flush();\r
-    }\r
-\r
-}\r
+/*
+ * model exporter for pmd-file(Ext1)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.MorphType;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+
+/**
+ * PMDファイルのエクスポーター(拡張1:英名対応)。
+ * <p>
+ * 任意のトゥーンファイル名対応以降のPMDファイルフォーマットを
+ * 使いたくない場合はこのエクスポーターを用いて出力せよ。
+ */
+public class PmdExporterExt1 extends PmdExporterBase{
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    public PmdExporterExt1(OutputStream stream)
+            throws NullPointerException{
+        super(stream);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param model {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws IllegalPmdException {@inheritDoc}
+     */
+    @Override
+    public void dumpPmdModel(PmdModel model)
+            throws IOException, IllegalPmdException{
+        super.dumpPmdModel(model);
+
+        dumpGlobalInfo(model);
+
+        return;
+    }
+
+    /**
+     * 英語名情報を出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字列が長すぎる。
+     */
+    private void dumpGlobalInfo(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        boolean hasGlobal = model.hasGlobalText();
+        byte globalFlag;
+        if(hasGlobal) globalFlag = 0x01;
+        else          globalFlag = 0x00;
+        dumpByte(globalFlag);
+
+        if(hasGlobal){
+            dumpBasicGlobal(model);
+            dumpBoneGlobal(model);
+            dumpMorphGlobal(model);
+            dumpBoneGroupGlobal(model);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * モデル基本情報を英語で出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字列が長すぎる。
+     */
+    private void dumpBasicGlobal(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        String modelName = model.getModelName().getGlobalText();
+        if(modelName == null) modelName = "";
+        dumpText(modelName, PmdLimits.MAXBYTES_MODELNAME);
+
+        String description = model.getDescription().getGlobalText();
+        if(description == null) description = "";
+        dumpText(description, PmdLimits.MAXBYTES_MODELDESC);
+
+        flush();
+    }
+
+    /**
+     * ボーン英語名情報を出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字列が長すぎる。
+     */
+    private void dumpBoneGlobal(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        for(BoneInfo bone : model.getBoneList()){
+            String boneName = bone.getBoneName().getGlobalText();
+            if(boneName == null) boneName = "";
+            dumpText(boneName, PmdLimits.MAXBYTES_BONENAME);
+        }
+
+        flush();
+    }
+
+    /**
+     * モーフ英語名情報を出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字列が長すぎる。
+     */
+    private void dumpMorphGlobal(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
+
+        for(MorphType type : MorphType.values()){
+            if(type.isBase()) continue;
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                String morphName = part.getMorphName().getGlobalText();
+                if(morphName == null) morphName = "";
+                dumpText(morphName, PmdLimits.MAXBYTES_MORPHNAME);
+            }
+        }
+
+        flush();
+    }
+
+    /**
+     * ボーングループ英語名情報を出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 文字列が長すぎる
+     */
+    private void dumpBoneGroupGlobal(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        for(BoneGroup group : model.getBoneGroupList()){
+            if(group.isDefaultBoneGroup()) continue;
+            String groupName = group.getGroupName().getGlobalText();
+            if(groupName == null) groupName = "";
+            dumpText(groupName, PmdLimits.MAXBYTES_BONEGROUPNAME);
+        }
+
+        flush();
+    }
+
+}
index fcd3b4f..9dbe738 100644 (file)
@@ -1,72 +1,72 @@
-/*\r
- * model exporter for pmd-file(Ext2)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.ToonMap;\r
-\r
-/**\r
- * PMDファイルのエクスポーター(拡張2:任意のトゥーンファイル名対応)。\r
- * <p>\r
- * 物理演算対応以降のPMDファイルフォーマットを\r
- * 使いたくない場合はこのエクスポーターを用いて出力せよ。\r
- */\r
-public class PmdExporterExt2 extends PmdExporterExt1{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public PmdExporterExt2(OutputStream stream)\r
-            throws NullPointerException{\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param model {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws IllegalPmdException {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void dumpPmdModel(PmdModel model)\r
-            throws IOException, IllegalPmdException{\r
-        super.dumpPmdModel(model);\r
-\r
-        dumpToonMap(model);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 独自トゥーンファイルテーブルを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException トゥーンファイル名が長すぎる\r
-     */\r
-    private void dumpToonMap(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        ToonMap map = model.getToonMap();\r
-\r
-        for(int idx = 0; idx < PmdLimits.TOON_FIXEDNUM; idx++){\r
-            String toonName = map.getIndexedToon(idx);\r
-            if(toonName == null) toonName = "";\r
-            dumpText(toonName, PmdLimits.MAXBYTES_TOONFILENAME);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * model exporter for pmd-file(Ext2)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.ToonMap;
+
+/**
+ * PMDファイルのエクスポーター(拡張2:任意のトゥーンファイル名対応)。
+ * <p>
+ * 物理演算対応以降のPMDファイルフォーマットを
+ * 使いたくない場合はこのエクスポーターを用いて出力せよ。
+ */
+public class PmdExporterExt2 extends PmdExporterExt1{
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    public PmdExporterExt2(OutputStream stream)
+            throws NullPointerException{
+        super(stream);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param model {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws IllegalPmdException {@inheritDoc}
+     */
+    @Override
+    public void dumpPmdModel(PmdModel model)
+            throws IOException, IllegalPmdException{
+        super.dumpPmdModel(model);
+
+        dumpToonMap(model);
+
+        return;
+    }
+
+    /**
+     * 独自トゥーンファイルテーブルを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException トゥーンファイル名が長すぎる
+     */
+    private void dumpToonMap(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        ToonMap map = model.getToonMap();
+
+        for(int idx = 0; idx < PmdLimits.TOON_FIXEDNUM; idx++){
+            String toonName = map.getIndexedToon(idx);
+            if(toonName == null) toonName = "";
+            dumpText(toonName, PmdLimits.MAXBYTES_TOONFILENAME);
+        }
+
+        flush();
+
+        return;
+    }
+
+}
index 08b07f7..0f2ca38 100644 (file)
-/*\r
- * model exporter for pmd-file(Ext3)\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.Deg3d;\r
-import jp.sourceforge.mikutoga.pmd.DynamicsInfo;\r
-import jp.sourceforge.mikutoga.pmd.JointInfo;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Rad3d;\r
-import jp.sourceforge.mikutoga.pmd.RigidGroup;\r
-import jp.sourceforge.mikutoga.pmd.RigidInfo;\r
-import jp.sourceforge.mikutoga.pmd.RigidShape;\r
-import jp.sourceforge.mikutoga.pmd.RigidShapeType;\r
-import jp.sourceforge.mikutoga.pmd.TripletRange;\r
-\r
-/**\r
- * PMDファイルのエクスポーター(拡張3:物理演算対応)。\r
- * <p>\r
- * 物理演算対応のPMDファイルフォーマットを\r
- * 使いたい場合はこのエクスポーターを用いて出力せよ。\r
- */\r
-public class PmdExporterExt3 extends PmdExporterExt2{\r
-\r
-    private static final short MASK_FULLCOLLISION = (short) 0xffff;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public PmdExporterExt3(OutputStream stream)\r
-            throws NullPointerException{\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param model {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     * @throws IllegalPmdException {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void dumpPmdModel(PmdModel model)\r
-            throws IOException, IllegalPmdException{\r
-        super.dumpPmdModel(model);\r
-\r
-        dumpRigidList(model);\r
-        dumpJointList(model);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体リストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 長すぎる剛体名\r
-     */\r
-    private void dumpRigidList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        List<RigidInfo> rigidList = model.getRigidList();\r
-        int rigidNum = rigidList.size();\r
-        dumpInt(rigidNum);\r
-\r
-        for(RigidInfo rigid : rigidList){\r
-            dumpRigid(rigid);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 個別の剛体情報を出力する。\r
-     * @param rigid 剛体\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 長すぎる剛体名\r
-     */\r
-    private void dumpRigid(RigidInfo rigid)\r
-            throws IOException, IllegalPmdTextException{\r
-        String rigidName = rigid.getRigidName().getPrimaryText();\r
-        dumpText(rigidName, PmdLimits.MAXBYTES_RIGIDNAME);\r
-\r
-        BoneInfo linkedBone = rigid.getLinkedBone();\r
-        if(linkedBone == null){\r
-            dumpShort(-1);\r
-        }else{\r
-            dumpShort(linkedBone.getSerialNumber());\r
-        }\r
-\r
-        RigidGroup group = rigid.getRigidGroup();\r
-        dumpByte(group.getSerialNumber());\r
-\r
-        short mask = MASK_FULLCOLLISION;\r
-        for(RigidGroup throughGroup : rigid.getThroughGroupColl()){\r
-            int serialId = throughGroup.getSerialNumber();\r
-            mask &= ~(0x0001 << serialId);\r
-        }\r
-        dumpShort(mask);\r
-\r
-        dumpRigidShape(rigid.getRigidShape());\r
-\r
-        dumpPos3d(rigid.getPosition());\r
-        dumpRad3d(rigid.getRotation());\r
-\r
-        dumpDynamics(rigid.getDynamicsInfo());\r
-\r
-        dumpByte(rigid.getBehaviorType().encode());\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 剛体形状を出力する。\r
-     * @param shape 剛体形状\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpRigidShape(RigidShape shape)\r
-            throws IOException{\r
-        RigidShapeType type = shape.getShapeType();\r
-        dumpByte(type.encode());\r
-\r
-        float width = shape.getWidth();\r
-        float height = shape.getHeight();\r
-        float depth = shape.getDepth();\r
-\r
-        dumpFloat(width);\r
-        dumpFloat(height);\r
-        dumpFloat(depth);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 力学設定を出力する。\r
-     * @param dynamics 力学設定\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private void dumpDynamics(DynamicsInfo dynamics)\r
-            throws IOException{\r
-        float mass        = dynamics.getMass();\r
-        float dampPos     = dynamics.getDampingPosition();\r
-        float dampRot     = dynamics.getDampingRotation();\r
-        float restitution = dynamics.getRestitution();\r
-        float friction    = dynamics.getFriction();\r
-\r
-        dumpFloat(mass);\r
-        dumpFloat(dampPos);\r
-        dumpFloat(dampRot);\r
-        dumpFloat(restitution);\r
-        dumpFloat(friction);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ジョイントリストを出力する。\r
-     * @param model モデルデータ\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 長すぎるジョイント名\r
-     */\r
-    private void dumpJointList(PmdModel model)\r
-            throws IOException, IllegalPmdTextException{\r
-        List<JointInfo> jointList = model.getJointList();\r
-        int jointNum = jointList.size();\r
-        dumpInt(jointNum);\r
-\r
-        for(JointInfo joint : jointList){\r
-            dumpJoint(joint);\r
-        }\r
-\r
-        flush();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 個別のジョイント情報を出力する。\r
-     * @param joint ジョイント\r
-     * @throws IOException 出力エラー\r
-     * @throws IllegalPmdTextException 長すぎるジョイント名\r
-     */\r
-    private void dumpJoint(JointInfo joint)\r
-            throws IOException, IllegalPmdTextException{\r
-        String jointName = joint.getJointName().getPrimaryText();\r
-        dumpText(jointName, PmdLimits.MAXBYTES_JOINTNAME);\r
-\r
-        RigidInfo rigidA = joint.getRigidA();\r
-        RigidInfo rigidB = joint.getRigidB();\r
-\r
-        dumpInt(rigidA.getSerialNumber());\r
-        dumpInt(rigidB.getSerialNumber());\r
-\r
-        dumpPos3d(joint.getPosition());\r
-        dumpRad3d(joint.getRotation());\r
-\r
-        dumpTripletRange(joint.getPositionRange());\r
-        dumpTripletRange(joint.getRotationRange());\r
-\r
-        dumpPos3d(joint.getElasticPosition());\r
-        dumpDeg3d(joint.getElasticRotation());\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 3次元範囲制約を出力する。\r
-     * @param range 3次元範囲制約\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpTripletRange(TripletRange range) throws IOException{\r
-        float xFrom = range.getXFrom();\r
-        float yFrom = range.getYFrom();\r
-        float zFrom = range.getZFrom();\r
-\r
-        dumpFloat(xFrom);\r
-        dumpFloat(yFrom);\r
-        dumpFloat(zFrom);\r
-\r
-        float xTo = range.getXTo();\r
-        float yTo = range.getYTo();\r
-        float zTo = range.getZTo();\r
-\r
-        dumpFloat(xTo);\r
-        dumpFloat(yTo);\r
-        dumpFloat(zTo);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ラジアンによる3次元姿勢情報を出力する。\r
-     * @param rad 3次元姿勢情報\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpRad3d(Rad3d rad) throws IOException{\r
-        float xVal = rad.getXRad();\r
-        float yVal = rad.getYRad();\r
-        float zVal = rad.getZRad();\r
-\r
-        dumpFloat(xVal);\r
-        dumpFloat(yVal);\r
-        dumpFloat(zVal);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 度数法による3次元姿勢情報を出力する。\r
-     * @param deg 3次元姿勢情報\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected void dumpDeg3d(Deg3d deg) throws IOException{\r
-        float xVal = deg.getXDeg();\r
-        float yVal = deg.getYDeg();\r
-        float zVal = deg.getZDeg();\r
-\r
-        dumpFloat(xVal);\r
-        dumpFloat(yVal);\r
-        dumpFloat(zVal);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * model exporter for pmd-file(Ext3)
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.Deg3d;
+import jp.sourceforge.mikutoga.pmd.DynamicsInfo;
+import jp.sourceforge.mikutoga.pmd.JointInfo;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Rad3d;
+import jp.sourceforge.mikutoga.pmd.RigidGroup;
+import jp.sourceforge.mikutoga.pmd.RigidInfo;
+import jp.sourceforge.mikutoga.pmd.RigidShape;
+import jp.sourceforge.mikutoga.pmd.RigidShapeType;
+import jp.sourceforge.mikutoga.pmd.TripletRange;
+
+/**
+ * PMDファイルのエクスポーター(拡張3:物理演算対応)。
+ * <p>
+ * 物理演算対応のPMDファイルフォーマットを
+ * 使いたい場合はこのエクスポーターを用いて出力せよ。
+ */
+public class PmdExporterExt3 extends PmdExporterExt2{
+
+    private static final short MASK_FULLCOLLISION = (short) 0xffff;
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @throws NullPointerException 引数がnull
+     */
+    public PmdExporterExt3(OutputStream stream)
+            throws NullPointerException{
+        super(stream);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param model {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws IllegalPmdException {@inheritDoc}
+     */
+    @Override
+    public void dumpPmdModel(PmdModel model)
+            throws IOException, IllegalPmdException{
+        super.dumpPmdModel(model);
+
+        dumpRigidList(model);
+        dumpJointList(model);
+
+        return;
+    }
+
+    /**
+     * 剛体リストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 長すぎる剛体名
+     */
+    private void dumpRigidList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        List<RigidInfo> rigidList = model.getRigidList();
+        int rigidNum = rigidList.size();
+        dumpInt(rigidNum);
+
+        for(RigidInfo rigid : rigidList){
+            dumpRigid(rigid);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 個別の剛体情報を出力する。
+     * @param rigid 剛体
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 長すぎる剛体名
+     */
+    private void dumpRigid(RigidInfo rigid)
+            throws IOException, IllegalPmdTextException{
+        String rigidName = rigid.getRigidName().getPrimaryText();
+        dumpText(rigidName, PmdLimits.MAXBYTES_RIGIDNAME);
+
+        BoneInfo linkedBone = rigid.getLinkedBone();
+        if(linkedBone == null){
+            dumpShort(-1);
+        }else{
+            dumpShort(linkedBone.getSerialNumber());
+        }
+
+        RigidGroup group = rigid.getRigidGroup();
+        dumpByte(group.getSerialNumber());
+
+        short mask = MASK_FULLCOLLISION;
+        for(RigidGroup throughGroup : rigid.getThroughGroupColl()){
+            int serialId = throughGroup.getSerialNumber();
+            mask &= ~(0x0001 << serialId);
+        }
+        dumpShort(mask);
+
+        dumpRigidShape(rigid.getRigidShape());
+
+        dumpPos3d(rigid.getPosition());
+        dumpRad3d(rigid.getRotation());
+
+        dumpDynamics(rigid.getDynamicsInfo());
+
+        dumpByte(rigid.getBehaviorType().encode());
+
+        return;
+    }
+
+    /**
+     * 剛体形状を出力する。
+     * @param shape 剛体形状
+     * @throws IOException 出力エラー
+     */
+    private void dumpRigidShape(RigidShape shape)
+            throws IOException{
+        RigidShapeType type = shape.getShapeType();
+        dumpByte(type.encode());
+
+        float width = shape.getWidth();
+        float height = shape.getHeight();
+        float depth = shape.getDepth();
+
+        dumpFloat(width);
+        dumpFloat(height);
+        dumpFloat(depth);
+
+        return;
+    }
+
+    /**
+     * 力学設定を出力する。
+     * @param dynamics 力学設定
+     * @throws IOException 出力エラー
+     */
+    private void dumpDynamics(DynamicsInfo dynamics)
+            throws IOException{
+        float mass        = dynamics.getMass();
+        float dampPos     = dynamics.getDampingPosition();
+        float dampRot     = dynamics.getDampingRotation();
+        float restitution = dynamics.getRestitution();
+        float friction    = dynamics.getFriction();
+
+        dumpFloat(mass);
+        dumpFloat(dampPos);
+        dumpFloat(dampRot);
+        dumpFloat(restitution);
+        dumpFloat(friction);
+
+        return;
+    }
+
+    /**
+     * ジョイントリストを出力する。
+     * @param model モデルデータ
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 長すぎるジョイント名
+     */
+    private void dumpJointList(PmdModel model)
+            throws IOException, IllegalPmdTextException{
+        List<JointInfo> jointList = model.getJointList();
+        int jointNum = jointList.size();
+        dumpInt(jointNum);
+
+        for(JointInfo joint : jointList){
+            dumpJoint(joint);
+        }
+
+        flush();
+
+        return;
+    }
+
+    /**
+     * 個別のジョイント情報を出力する。
+     * @param joint ジョイント
+     * @throws IOException 出力エラー
+     * @throws IllegalPmdTextException 長すぎるジョイント名
+     */
+    private void dumpJoint(JointInfo joint)
+            throws IOException, IllegalPmdTextException{
+        String jointName = joint.getJointName().getPrimaryText();
+        dumpText(jointName, PmdLimits.MAXBYTES_JOINTNAME);
+
+        RigidInfo rigidA = joint.getRigidA();
+        RigidInfo rigidB = joint.getRigidB();
+
+        dumpInt(rigidA.getSerialNumber());
+        dumpInt(rigidB.getSerialNumber());
+
+        dumpPos3d(joint.getPosition());
+        dumpRad3d(joint.getRotation());
+
+        dumpTripletRange(joint.getPositionRange());
+        dumpTripletRange(joint.getRotationRange());
+
+        dumpPos3d(joint.getElasticPosition());
+        dumpDeg3d(joint.getElasticRotation());
+
+        return;
+    }
+
+    /**
+     * 3次元範囲制約を出力する。
+     * @param range 3次元範囲制約
+     * @throws IOException 出力エラー
+     */
+    protected void dumpTripletRange(TripletRange range) throws IOException{
+        float xFrom = range.getXFrom();
+        float yFrom = range.getYFrom();
+        float zFrom = range.getZFrom();
+
+        dumpFloat(xFrom);
+        dumpFloat(yFrom);
+        dumpFloat(zFrom);
+
+        float xTo = range.getXTo();
+        float yTo = range.getYTo();
+        float zTo = range.getZTo();
+
+        dumpFloat(xTo);
+        dumpFloat(yTo);
+        dumpFloat(zTo);
+
+        return;
+    }
+
+    /**
+     * ラジアンによる3次元姿勢情報を出力する。
+     * @param rad 3次元姿勢情報
+     * @throws IOException 出力エラー
+     */
+    protected void dumpRad3d(Rad3d rad) throws IOException{
+        float xVal = rad.getXRad();
+        float yVal = rad.getYRad();
+        float zVal = rad.getZRad();
+
+        dumpFloat(xVal);
+        dumpFloat(yVal);
+        dumpFloat(zVal);
+
+        return;
+    }
+
+    /**
+     * 度数法による3次元姿勢情報を出力する。
+     * @param deg 3次元姿勢情報
+     * @throws IOException 出力エラー
+     */
+    protected void dumpDeg3d(Deg3d deg) throws IOException{
+        float xVal = deg.getXDeg();
+        float yVal = deg.getYDeg();
+        float zVal = deg.getZDeg();
+
+        dumpFloat(xVal);
+        dumpFloat(yVal);
+        dumpFloat(zVal);
+
+        return;
+    }
+
+}
index 56f44ae..a1eb5a8 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * PMDモデルファイル(*.pmd)用エクスポーター。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdexporter;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * PMDモデルファイル(*.pmd)用エクスポーター。
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdexporter;
+
+/* EOF */
index 0dca521..28a00ea 100644 (file)
-/*\r
- * building bone information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.Iterator;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdBoneHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.BoneType;\r
-import jp.sourceforge.mikutoga.pmd.IKChain;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-\r
-/**\r
- * ボーン関係の通知をパーサから受け取る。\r
- */\r
-class BoneBuilder implements PmdBoneHandler {\r
-\r
-    private final List<BoneInfo> boneList;\r
-    private Iterator<BoneInfo> boneIt;\r
-    private BoneInfo currentBone = null;\r
-\r
-    private final List<IKChain> ikChainList;\r
-    private Iterator<IKChain> ikChainIt;\r
-    private IKChain currentIkChain = null;\r
-\r
-    private final List<BoneGroup> boneGroupList;\r
-    private Iterator<BoneGroup> boneGroupIt;\r
-    private BoneGroup currentBoneGroup = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    BoneBuilder(PmdModel model){\r
-        super();\r
-\r
-        this.boneList      = model.getBoneList();\r
-        this.ikChainList   = model.getIKChainList();\r
-        this.boneGroupList = model.getBoneGroupList();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage instanceof PmdBoneStage;\r
-\r
-        if(stage == PmdBoneHandler.BONE_LIST){\r
-            ListUtil.prepareDefConsList(this.boneList, BoneInfo.class, loops);\r
-            ListUtil.assignIndexedSerial(this.boneList);\r
-\r
-            this.boneIt = this.boneList.iterator();\r
-            if(this.boneIt.hasNext()){\r
-                this.currentBone = this.boneIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.IK_LIST){\r
-            ListUtil.prepareDefConsList(this.ikChainList,\r
-                                        IKChain.class,\r
-                                        loops );\r
-\r
-            this.ikChainIt = this.ikChainList.iterator();\r
-            if(this.ikChainIt.hasNext()){\r
-                this.currentIkChain = this.ikChainIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){\r
-            ListUtil.prepareDefConsList(this.boneGroupList,\r
-                                        BoneGroup.class,\r
-                                        loops + 1 );\r
-            ListUtil.assignIndexedSerial(this.boneGroupList);\r
-\r
-            this.boneGroupIt = this.boneGroupList.iterator();\r
-\r
-            assert this.boneGroupIt.hasNext();\r
-            this.boneGroupIt.next();     // デフォルトボーングループを読み飛ばす\r
-\r
-            if(this.boneGroupIt.hasNext()){\r
-                this.currentBoneGroup = this.boneGroupIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){\r
-            //NOTHING\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage instanceof PmdBoneStage;\r
-\r
-        if(stage == PmdBoneHandler.BONE_LIST){\r
-            if(this.boneIt.hasNext()){\r
-                this.currentBone = this.boneIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.IK_LIST){\r
-            if(this.ikChainIt.hasNext()){\r
-                this.currentIkChain = this.ikChainIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){\r
-            if(this.boneGroupIt.hasNext()){\r
-                this.currentBoneGroup = this.boneGroupIt.next();\r
-            }\r
-        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){\r
-            //NOTHING\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage instanceof PmdBoneStage;\r
-\r
-        if(stage == PmdBoneHandler.BONE_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.IK_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){\r
-            //NOTHING\r
-        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){\r
-            pickOrphanBone();\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 所属グループの無いボーンをデフォルトボーングループへ登録する。\r
-     */\r
-    private void pickOrphanBone(){\r
-        List<BoneInfo> orpahnList = new LinkedList<BoneInfo>();\r
-        orpahnList.addAll(this.boneList);\r
-        for(BoneGroup group : this.boneGroupList){\r
-            orpahnList.removeAll(group.getBoneList());\r
-        }\r
-\r
-        BoneGroup defaultGroup = this.boneGroupList.get(0);\r
-        defaultGroup.getBoneList().addAll(orpahnList);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param boneName {@inheritDoc}\r
-     * @param boneKind {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdBoneInfo(String boneName, byte boneKind){\r
-        this.currentBone.getBoneName().setPrimaryText(boneName);\r
-        BoneType type = BoneType.decode(boneKind);\r
-        this.currentBone.setBoneType(type);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param parentId {@inheritDoc}\r
-     * @param tailId {@inheritDoc}\r
-     * @param ikId {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdBoneLink(int parentId, int tailId, int ikId){\r
-        BoneInfo prevBone = null;\r
-        if(0 <= parentId && parentId < PmdLimits.MAX_BONE){\r
-            prevBone = this.boneList.get(parentId);\r
-        }\r
-\r
-        BoneInfo nextBone = null;\r
-        if(tailId != 0){\r
-            nextBone = this.boneList.get(tailId);\r
-        }\r
-\r
-        BoneInfo ikBone = null;\r
-        if(this.currentBone.getBoneType() == BoneType.LINKEDROT){\r
-            ikBone = null;\r
-            int ratio = ikId;\r
-            this.currentBone.setRotationRatio(ratio);\r
-        }else if(0 < ikId && ikId < PmdLimits.MAX_BONE){\r
-            ikBone = this.boneList.get(ikId);\r
-        }\r
-\r
-        this.currentBone.setPrevBone(prevBone);\r
-        this.currentBone.setNextBone(nextBone);\r
-        this.currentBone.setIKBone(ikBone);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param xPos {@inheritDoc}\r
-     * @param yPos {@inheritDoc}\r
-     * @param zPos {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdBonePosition(float xPos, float yPos, float zPos){\r
-        Pos3d position = this.currentBone.getPosition();\r
-        position.setXPos(xPos);\r
-        position.setYPos(yPos);\r
-        position.setZPos(zPos);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param boneId {@inheritDoc}\r
-     * @param targetId {@inheritDoc}\r
-     * @param depth {@inheritDoc}\r
-     * @param weight {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdIKInfo(int boneId, int targetId, int depth, float weight){\r
-        BoneInfo bone = this.boneList.get(boneId);\r
-        this.currentIkChain.setIkBone(bone);\r
-\r
-        BoneInfo target = this.boneList.get(targetId);\r
-        this.currentIkChain.getChainedBoneList().add(0, target);\r
-\r
-        this.currentIkChain.setIKDepth(depth);\r
-        this.currentIkChain.setIKWeight(weight);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param childId {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdIKChainInfo(int childId){\r
-        BoneInfo chain = this.boneList.get(childId);\r
-        this.currentIkChain.getChainedBoneList().add(chain);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param groupName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdBoneGroupInfo(String groupName){\r
-        this.currentBoneGroup.getGroupName().setPrimaryText(groupName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param boneId {@inheritDoc}\r
-     * @param groupId {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdGroupedBoneInfo(int boneId, int groupId){\r
-        BoneInfo bone = this.boneList.get(boneId);\r
-        BoneGroup group = this.boneGroupList.get(groupId);\r
-        group.getBoneList().add(bone);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building bone information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdBoneHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.BoneType;
+import jp.sourceforge.mikutoga.pmd.IKChain;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+
+/**
+ * ボーン関係の通知をパーサから受け取る。
+ */
+class BoneBuilder implements PmdBoneHandler {
+
+    private final List<BoneInfo> boneList;
+    private Iterator<BoneInfo> boneIt;
+    private BoneInfo currentBone = null;
+
+    private final List<IKChain> ikChainList;
+    private Iterator<IKChain> ikChainIt;
+    private IKChain currentIkChain = null;
+
+    private final List<BoneGroup> boneGroupList;
+    private Iterator<BoneGroup> boneGroupIt;
+    private BoneGroup currentBoneGroup = null;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    BoneBuilder(PmdModel model){
+        super();
+
+        this.boneList      = model.getBoneList();
+        this.ikChainList   = model.getIKChainList();
+        this.boneGroupList = model.getBoneGroupList();
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage instanceof PmdBoneStage;
+
+        if(stage == PmdBoneHandler.BONE_LIST){
+            ListUtil.prepareDefConsList(this.boneList, BoneInfo.class, loops);
+            ListUtil.assignIndexedSerial(this.boneList);
+
+            this.boneIt = this.boneList.iterator();
+            if(this.boneIt.hasNext()){
+                this.currentBone = this.boneIt.next();
+            }
+        }else if(stage == PmdBoneHandler.IK_LIST){
+            ListUtil.prepareDefConsList(this.ikChainList,
+                                        IKChain.class,
+                                        loops );
+
+            this.ikChainIt = this.ikChainList.iterator();
+            if(this.ikChainIt.hasNext()){
+                this.currentIkChain = this.ikChainIt.next();
+            }
+        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
+            ListUtil.prepareDefConsList(this.boneGroupList,
+                                        BoneGroup.class,
+                                        loops + 1 );
+            ListUtil.assignIndexedSerial(this.boneGroupList);
+
+            this.boneGroupIt = this.boneGroupList.iterator();
+
+            assert this.boneGroupIt.hasNext();
+            this.boneGroupIt.next();     // デフォルトボーングループを読み飛ばす
+
+            if(this.boneGroupIt.hasNext()){
+                this.currentBoneGroup = this.boneGroupIt.next();
+            }
+        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
+            //NOTHING
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage instanceof PmdBoneStage;
+
+        if(stage == PmdBoneHandler.BONE_LIST){
+            if(this.boneIt.hasNext()){
+                this.currentBone = this.boneIt.next();
+            }
+        }else if(stage == PmdBoneHandler.IK_LIST){
+            if(this.ikChainIt.hasNext()){
+                this.currentIkChain = this.ikChainIt.next();
+            }
+        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
+            if(this.boneGroupIt.hasNext()){
+                this.currentBoneGroup = this.boneGroupIt.next();
+            }
+        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
+            //NOTHING
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage instanceof PmdBoneStage;
+
+        if(stage == PmdBoneHandler.BONE_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.IK_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
+            //NOTHING
+        }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
+            pickOrphanBone();
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * 所属グループの無いボーンをデフォルトボーングループへ登録する。
+     */
+    private void pickOrphanBone(){
+        List<BoneInfo> orpahnList = new LinkedList<BoneInfo>();
+        orpahnList.addAll(this.boneList);
+        for(BoneGroup group : this.boneGroupList){
+            orpahnList.removeAll(group.getBoneList());
+        }
+
+        BoneGroup defaultGroup = this.boneGroupList.get(0);
+        defaultGroup.getBoneList().addAll(orpahnList);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param boneName {@inheritDoc}
+     * @param boneKind {@inheritDoc}
+     */
+    @Override
+    public void pmdBoneInfo(String boneName, byte boneKind){
+        this.currentBone.getBoneName().setPrimaryText(boneName);
+        BoneType type = BoneType.decode(boneKind);
+        this.currentBone.setBoneType(type);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param parentId {@inheritDoc}
+     * @param tailId {@inheritDoc}
+     * @param ikId {@inheritDoc}
+     */
+    @Override
+    public void pmdBoneLink(int parentId, int tailId, int ikId){
+        BoneInfo prevBone = null;
+        if(0 <= parentId && parentId < PmdLimits.MAX_BONE){
+            prevBone = this.boneList.get(parentId);
+        }
+
+        BoneInfo nextBone = null;
+        if(tailId != 0){
+            nextBone = this.boneList.get(tailId);
+        }
+
+        BoneInfo ikBone = null;
+        if(this.currentBone.getBoneType() == BoneType.LINKEDROT){
+            ikBone = null;
+            int ratio = ikId;
+            this.currentBone.setRotationRatio(ratio);
+        }else if(0 < ikId && ikId < PmdLimits.MAX_BONE){
+            ikBone = this.boneList.get(ikId);
+        }
+
+        this.currentBone.setPrevBone(prevBone);
+        this.currentBone.setNextBone(nextBone);
+        this.currentBone.setIKBone(ikBone);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param xPos {@inheritDoc}
+     * @param yPos {@inheritDoc}
+     * @param zPos {@inheritDoc}
+     */
+    @Override
+    public void pmdBonePosition(float xPos, float yPos, float zPos){
+        Pos3d position = this.currentBone.getPosition();
+        position.setXPos(xPos);
+        position.setYPos(yPos);
+        position.setZPos(zPos);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param boneId {@inheritDoc}
+     * @param targetId {@inheritDoc}
+     * @param depth {@inheritDoc}
+     * @param weight {@inheritDoc}
+     */
+    @Override
+    public void pmdIKInfo(int boneId, int targetId, int depth, float weight){
+        BoneInfo bone = this.boneList.get(boneId);
+        this.currentIkChain.setIkBone(bone);
+
+        BoneInfo target = this.boneList.get(targetId);
+        this.currentIkChain.getChainedBoneList().add(0, target);
+
+        this.currentIkChain.setIKDepth(depth);
+        this.currentIkChain.setIKWeight(weight);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param childId {@inheritDoc}
+     */
+    @Override
+    public void pmdIKChainInfo(int childId){
+        BoneInfo chain = this.boneList.get(childId);
+        this.currentIkChain.getChainedBoneList().add(chain);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param groupName {@inheritDoc}
+     */
+    @Override
+    public void pmdBoneGroupInfo(String groupName){
+        this.currentBoneGroup.getGroupName().setPrimaryText(groupName);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param boneId {@inheritDoc}
+     * @param groupId {@inheritDoc}
+     */
+    @Override
+    public void pmdGroupedBoneInfo(int boneId, int groupId){
+        BoneInfo bone = this.boneList.get(boneId);
+        BoneGroup group = this.boneGroupList.get(groupId);
+        group.getBoneList().add(bone);
+        return;
+    }
+
+}
index ca619a4..b2a38e2 100644 (file)
-/*\r
- * building joint information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdJointHandler;\r
-import jp.sourceforge.mikutoga.pmd.Deg3d;\r
-import jp.sourceforge.mikutoga.pmd.JointInfo;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Rad3d;\r
-import jp.sourceforge.mikutoga.pmd.RigidInfo;\r
-import jp.sourceforge.mikutoga.pmd.TripletRange;\r
-\r
-/**\r
- * ジョイント関係の通知をパーサから受け取る。\r
- */\r
-class JointBuilder implements PmdJointHandler {\r
-\r
-    private final List<RigidInfo> rigidList;\r
-\r
-    private final List<JointInfo> jointList;\r
-    private Iterator<JointInfo> jointIt;\r
-    private JointInfo currentJoint = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    JointBuilder(PmdModel model){\r
-        super();\r
-        this.rigidList = model.getRigidList();\r
-        this.jointList = model.getJointList();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage == PmdJointHandler.JOINT_LIST;\r
-\r
-        ListUtil.prepareDefConsList(this.jointList, JointInfo.class, loops);\r
-\r
-        this.jointIt = this.jointList.iterator();\r
-        if(this.jointIt.hasNext()){\r
-            this.currentJoint = this.jointIt.next();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage == PmdJointHandler.JOINT_LIST;\r
-\r
-        if(this.jointIt.hasNext()){\r
-            this.currentJoint = this.jointIt.next();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage == PmdJointHandler.JOINT_LIST;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param jointName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdJointName(String jointName){\r
-        this.currentJoint.getJointName().setPrimaryText(jointName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param rigidIdA {@inheritDoc}\r
-     * @param rigidIdB {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdJointLink(int rigidIdA, int rigidIdB){\r
-        RigidInfo rigidA = this.rigidList.get(rigidIdA);\r
-        RigidInfo rigidB = this.rigidList.get(rigidIdB);\r
-        this.currentJoint.setRigidPair(rigidA, rigidB);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param posX {@inheritDoc}\r
-     * @param posY {@inheritDoc}\r
-     * @param posZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdJointPosition(float posX, float posY, float posZ){\r
-        Pos3d position = this.currentJoint.getPosition();\r
-        position.setXPos(posX);\r
-        position.setYPos(posY);\r
-        position.setZPos(posZ);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param rotX {@inheritDoc}\r
-     * @param rotY {@inheritDoc}\r
-     * @param rotZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdJointRotation(float rotX, float rotY, float rotZ){\r
-        Rad3d rotation = this.currentJoint.getRotation();\r
-        rotation.setXRad(rotX);\r
-        rotation.setYRad(rotY);\r
-        rotation.setZRad(rotZ);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param posXlim1 {@inheritDoc}\r
-     * @param posXlim2 {@inheritDoc}\r
-     * @param posYlim1 {@inheritDoc}\r
-     * @param posYlim2 {@inheritDoc}\r
-     * @param posZlim1 {@inheritDoc}\r
-     * @param posZlim2 {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdPositionLimit(float posXlim1, float posXlim2,\r
-                                 float posYlim1, float posYlim2,\r
-                                 float posZlim1, float posZlim2){\r
-        TripletRange range = this.currentJoint.getPositionRange();\r
-        range.setXRange(posXlim1, posXlim2);\r
-        range.setYRange(posYlim1, posYlim2);\r
-        range.setZRange(posZlim1, posZlim2);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param rotXlim1 {@inheritDoc}\r
-     * @param rotXlim2 {@inheritDoc}\r
-     * @param rotYlim1 {@inheritDoc}\r
-     * @param rotYlim2 {@inheritDoc}\r
-     * @param rotZlim1 {@inheritDoc}\r
-     * @param rotZlim2 {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRotationLimit(float rotXlim1, float rotXlim2,\r
-                                 float rotYlim1, float rotYlim2,\r
-                                 float rotZlim1, float rotZlim2){\r
-        TripletRange range = this.currentJoint.getRotationRange();\r
-        range.setXRange(rotXlim1, rotXlim2);\r
-        range.setYRange(rotYlim1, rotYlim2);\r
-        range.setZRange(rotZlim1, rotZlim2);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param elasticPosX {@inheritDoc}\r
-     * @param elasticPosY {@inheritDoc}\r
-     * @param elasticPosZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdElasticPosition(float elasticPosX,\r
-                                   float elasticPosY,\r
-                                   float elasticPosZ){\r
-        Pos3d position = this.currentJoint.getElasticPosition();\r
-        position.setXPos(elasticPosX);\r
-        position.setYPos(elasticPosY);\r
-        position.setZPos(elasticPosZ);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param elasticRotX {@inheritDoc}\r
-     * @param elasticRotY {@inheritDoc}\r
-     * @param elasticRotZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdElasticRotation(float elasticRotX,\r
-                                   float elasticRotY,\r
-                                   float elasticRotZ){\r
-        Deg3d rotation = this.currentJoint.getElasticRotation();\r
-        rotation.setXDeg(elasticRotX);\r
-        rotation.setYDeg(elasticRotY);\r
-        rotation.setZDeg(elasticRotZ);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building joint information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdJointHandler;
+import jp.sourceforge.mikutoga.pmd.Deg3d;
+import jp.sourceforge.mikutoga.pmd.JointInfo;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Rad3d;
+import jp.sourceforge.mikutoga.pmd.RigidInfo;
+import jp.sourceforge.mikutoga.pmd.TripletRange;
+
+/**
+ * ジョイント関係の通知をパーサから受け取る。
+ */
+class JointBuilder implements PmdJointHandler {
+
+    private final List<RigidInfo> rigidList;
+
+    private final List<JointInfo> jointList;
+    private Iterator<JointInfo> jointIt;
+    private JointInfo currentJoint = null;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    JointBuilder(PmdModel model){
+        super();
+        this.rigidList = model.getRigidList();
+        this.jointList = model.getJointList();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage == PmdJointHandler.JOINT_LIST;
+
+        ListUtil.prepareDefConsList(this.jointList, JointInfo.class, loops);
+
+        this.jointIt = this.jointList.iterator();
+        if(this.jointIt.hasNext()){
+            this.currentJoint = this.jointIt.next();
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage == PmdJointHandler.JOINT_LIST;
+
+        if(this.jointIt.hasNext()){
+            this.currentJoint = this.jointIt.next();
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage == PmdJointHandler.JOINT_LIST;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param jointName {@inheritDoc}
+     */
+    @Override
+    public void pmdJointName(String jointName){
+        this.currentJoint.getJointName().setPrimaryText(jointName);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param rigidIdA {@inheritDoc}
+     * @param rigidIdB {@inheritDoc}
+     */
+    @Override
+    public void pmdJointLink(int rigidIdA, int rigidIdB){
+        RigidInfo rigidA = this.rigidList.get(rigidIdA);
+        RigidInfo rigidB = this.rigidList.get(rigidIdB);
+        this.currentJoint.setRigidPair(rigidA, rigidB);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param posX {@inheritDoc}
+     * @param posY {@inheritDoc}
+     * @param posZ {@inheritDoc}
+     */
+    @Override
+    public void pmdJointPosition(float posX, float posY, float posZ){
+        Pos3d position = this.currentJoint.getPosition();
+        position.setXPos(posX);
+        position.setYPos(posY);
+        position.setZPos(posZ);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param rotX {@inheritDoc}
+     * @param rotY {@inheritDoc}
+     * @param rotZ {@inheritDoc}
+     */
+    @Override
+    public void pmdJointRotation(float rotX, float rotY, float rotZ){
+        Rad3d rotation = this.currentJoint.getRotation();
+        rotation.setXRad(rotX);
+        rotation.setYRad(rotY);
+        rotation.setZRad(rotZ);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param posXlim1 {@inheritDoc}
+     * @param posXlim2 {@inheritDoc}
+     * @param posYlim1 {@inheritDoc}
+     * @param posYlim2 {@inheritDoc}
+     * @param posZlim1 {@inheritDoc}
+     * @param posZlim2 {@inheritDoc}
+     */
+    @Override
+    public void pmdPositionLimit(float posXlim1, float posXlim2,
+                                 float posYlim1, float posYlim2,
+                                 float posZlim1, float posZlim2){
+        TripletRange range = this.currentJoint.getPositionRange();
+        range.setXRange(posXlim1, posXlim2);
+        range.setYRange(posYlim1, posYlim2);
+        range.setZRange(posZlim1, posZlim2);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param rotXlim1 {@inheritDoc}
+     * @param rotXlim2 {@inheritDoc}
+     * @param rotYlim1 {@inheritDoc}
+     * @param rotYlim2 {@inheritDoc}
+     * @param rotZlim1 {@inheritDoc}
+     * @param rotZlim2 {@inheritDoc}
+     */
+    @Override
+    public void pmdRotationLimit(float rotXlim1, float rotXlim2,
+                                 float rotYlim1, float rotYlim2,
+                                 float rotZlim1, float rotZlim2){
+        TripletRange range = this.currentJoint.getRotationRange();
+        range.setXRange(rotXlim1, rotXlim2);
+        range.setYRange(rotYlim1, rotYlim2);
+        range.setZRange(rotZlim1, rotZlim2);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param elasticPosX {@inheritDoc}
+     * @param elasticPosY {@inheritDoc}
+     * @param elasticPosZ {@inheritDoc}
+     */
+    @Override
+    public void pmdElasticPosition(float elasticPosX,
+                                   float elasticPosY,
+                                   float elasticPosZ){
+        Pos3d position = this.currentJoint.getElasticPosition();
+        position.setXPos(elasticPosX);
+        position.setYPos(elasticPosY);
+        position.setZPos(elasticPosZ);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param elasticRotX {@inheritDoc}
+     * @param elasticRotY {@inheritDoc}
+     * @param elasticRotZ {@inheritDoc}
+     */
+    @Override
+    public void pmdElasticRotation(float elasticRotX,
+                                   float elasticRotY,
+                                   float elasticRotZ){
+        Deg3d rotation = this.currentJoint.getElasticRotation();
+        rotation.setXDeg(elasticRotX);
+        rotation.setYDeg(elasticRotY);
+        rotation.setZDeg(elasticRotZ);
+        return;
+    }
+
+}
index 11a99ec..9d7c3cc 100644 (file)
-/*\r
- * building material information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.awt.Color;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdMaterialHandler;\r
-import jp.sourceforge.mikutoga.pmd.Material;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.ShadeInfo;\r
-import jp.sourceforge.mikutoga.pmd.Surface;\r
-import jp.sourceforge.mikutoga.pmd.ToonMap;\r
-\r
-/**\r
- * マテリアル素材関連の通知をパーサから受け取る。\r
- */\r
-class MaterialBuilder implements PmdMaterialHandler {\r
-\r
-    private final List<Material> materialList;\r
-    private Iterator<Material> materialIt;\r
-    private Material currentMaterial = null;\r
-\r
-    private final List<Surface> surfacelList;\r
-    private Iterator<Surface> surfaceIt;\r
-\r
-    private final ToonMap toonMap;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    MaterialBuilder(PmdModel model){\r
-        super();\r
-\r
-        this.materialList = model.getMaterialList();\r
-        this.surfacelList = model.getSurfaceList();\r
-        this.toonMap = model.getToonMap();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage == PmdMaterialHandler.MATERIAL_LIST;\r
-\r
-        ListUtil.prepareDefConsList(this.materialList, Material.class, loops);\r
-\r
-        this.materialIt = this.materialList.iterator();\r
-        if(this.materialIt.hasNext()){\r
-            this.currentMaterial = this.materialIt.next();\r
-        }\r
-\r
-        this.surfaceIt = this.surfacelList.iterator();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage == PmdMaterialHandler.MATERIAL_LIST;\r
-\r
-        if(this.materialIt.hasNext()){\r
-            this.currentMaterial = this.materialIt.next();\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage == PmdMaterialHandler.MATERIAL_LIST;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param red {@inheritDoc}\r
-     * @param green {@inheritDoc}\r
-     * @param blue {@inheritDoc}\r
-     * @param alpha {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMaterialDiffuse(float red,\r
-                                   float green,\r
-                                   float blue,\r
-                                   float alpha ){\r
-        Color diffuse = new Color(red, green, blue, alpha);\r
-        this.currentMaterial.setDiffuseColor(diffuse);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param red {@inheritDoc}\r
-     * @param green {@inheritDoc}\r
-     * @param blue {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMaterialAmbient(float red,\r
-                                   float green,\r
-                                   float blue ){\r
-        Color ambient = new Color(red, green, blue);\r
-        this.currentMaterial.setAmbientColor(ambient);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param red {@inheritDoc}\r
-     * @param green {@inheritDoc}\r
-     * @param blue {@inheritDoc}\r
-     * @param shininess {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMaterialSpecular(float red,\r
-                                    float green,\r
-                                    float blue,\r
-                                    float shininess ){\r
-        Color specular = new Color(red, green, blue);\r
-        this.currentMaterial.setSpecularColor(specular);\r
-        this.currentMaterial.setShininess(shininess);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param hasEdge {@inheritDoc}\r
-     * @param vertexNum {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMaterialInfo(boolean hasEdge, int vertexNum){\r
-        this.currentMaterial.setEdgeAppearance(hasEdge);\r
-\r
-        List<Surface> list = this.currentMaterial.getSurfaceList();\r
-\r
-        int surfaceNum = vertexNum / 3;\r
-        for(int ct = 1; ct <= surfaceNum; ct++){\r
-            Surface surface = this.surfaceIt.next();\r
-            list.add(surface);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param toonIdx {@inheritDoc}\r
-     * @param textureFile {@inheritDoc}\r
-     * @param sphereFile {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMaterialShading(int toonIdx,\r
-                                   String textureFile,\r
-                                   String sphereFile ){\r
-        ShadeInfo info = this.currentMaterial.getShadeInfo();\r
-\r
-        ToonMap map = this.toonMap;\r
-\r
-        info.setToonMap(map);\r
-        info.setToonIndex(toonIdx);\r
-        info.setTextureFileName(textureFile);\r
-        info.setSpheremapFileName(sphereFile);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building material information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.awt.Color;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdMaterialHandler;
+import jp.sourceforge.mikutoga.pmd.Material;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.ShadeInfo;
+import jp.sourceforge.mikutoga.pmd.Surface;
+import jp.sourceforge.mikutoga.pmd.ToonMap;
+
+/**
+ * マテリアル素材関連の通知をパーサから受け取る。
+ */
+class MaterialBuilder implements PmdMaterialHandler {
+
+    private final List<Material> materialList;
+    private Iterator<Material> materialIt;
+    private Material currentMaterial = null;
+
+    private final List<Surface> surfacelList;
+    private Iterator<Surface> surfaceIt;
+
+    private final ToonMap toonMap;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    MaterialBuilder(PmdModel model){
+        super();
+
+        this.materialList = model.getMaterialList();
+        this.surfacelList = model.getSurfaceList();
+        this.toonMap = model.getToonMap();
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage == PmdMaterialHandler.MATERIAL_LIST;
+
+        ListUtil.prepareDefConsList(this.materialList, Material.class, loops);
+
+        this.materialIt = this.materialList.iterator();
+        if(this.materialIt.hasNext()){
+            this.currentMaterial = this.materialIt.next();
+        }
+
+        this.surfaceIt = this.surfacelList.iterator();
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage == PmdMaterialHandler.MATERIAL_LIST;
+
+        if(this.materialIt.hasNext()){
+            this.currentMaterial = this.materialIt.next();
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage == PmdMaterialHandler.MATERIAL_LIST;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param red {@inheritDoc}
+     * @param green {@inheritDoc}
+     * @param blue {@inheritDoc}
+     * @param alpha {@inheritDoc}
+     */
+    @Override
+    public void pmdMaterialDiffuse(float red,
+                                   float green,
+                                   float blue,
+                                   float alpha ){
+        Color diffuse = new Color(red, green, blue, alpha);
+        this.currentMaterial.setDiffuseColor(diffuse);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param red {@inheritDoc}
+     * @param green {@inheritDoc}
+     * @param blue {@inheritDoc}
+     */
+    @Override
+    public void pmdMaterialAmbient(float red,
+                                   float green,
+                                   float blue ){
+        Color ambient = new Color(red, green, blue);
+        this.currentMaterial.setAmbientColor(ambient);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param red {@inheritDoc}
+     * @param green {@inheritDoc}
+     * @param blue {@inheritDoc}
+     * @param shininess {@inheritDoc}
+     */
+    @Override
+    public void pmdMaterialSpecular(float red,
+                                    float green,
+                                    float blue,
+                                    float shininess ){
+        Color specular = new Color(red, green, blue);
+        this.currentMaterial.setSpecularColor(specular);
+        this.currentMaterial.setShininess(shininess);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param hasEdge {@inheritDoc}
+     * @param vertexNum {@inheritDoc}
+     */
+    @Override
+    public void pmdMaterialInfo(boolean hasEdge, int vertexNum){
+        this.currentMaterial.setEdgeAppearance(hasEdge);
+
+        List<Surface> list = this.currentMaterial.getSurfaceList();
+
+        int surfaceNum = vertexNum / 3;
+        for(int ct = 1; ct <= surfaceNum; ct++){
+            Surface surface = this.surfaceIt.next();
+            list.add(surface);
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param toonIdx {@inheritDoc}
+     * @param textureFile {@inheritDoc}
+     * @param sphereFile {@inheritDoc}
+     */
+    @Override
+    public void pmdMaterialShading(int toonIdx,
+                                   String textureFile,
+                                   String sphereFile ){
+        ShadeInfo info = this.currentMaterial.getShadeInfo();
+
+        ToonMap map = this.toonMap;
+
+        info.setToonMap(map);
+        info.setToonIndex(toonIdx);
+        info.setTextureFileName(textureFile);
+        info.setSpheremapFileName(sphereFile);
+
+        return;
+    }
+
+}
index 49e0650..40b0789 100644 (file)
-/*\r
- * building morph information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdMorphHandler;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.MorphType;\r
-import jp.sourceforge.mikutoga.pmd.MorphVertex;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Vertex;\r
-\r
-/**\r
- * モーフ関係の通知をパーサから受け取る。\r
- */\r
-class MorphBuilder implements PmdMorphHandler {\r
-\r
-    private final Map<MorphType, List<MorphPart>> morphMap;\r
-\r
-    private List<MorphPart> morphPartList;\r
-    private Iterator<MorphPart> morphPartIt;\r
-    private MorphPart currentMorphPart;\r
-    private final List<Vertex> vertexList;\r
-\r
-    private final List<Vertex> morphVertexList = new ArrayList<Vertex>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    MorphBuilder(PmdModel model){\r
-        super();\r
-        this.vertexList = model.getVertexList();\r
-        this.morphMap = model.getMorphMap();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイル中の出現順で各モーフを格納するためのリストを設定する。\r
-     * 主な用途はモーフ英名との突き合わせ作業。\r
-     * @param list モーフ格納リスト\r
-     */\r
-    void setMorphPartList(List<MorphPart> list){\r
-        this.morphPartList = list;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage instanceof PmdMorphStage;\r
-\r
-        if(stage == PmdMorphHandler.MORPH_LIST){\r
-            ListUtil.prepareDefConsList(this.morphPartList,\r
-                                        MorphPart.class,\r
-                                        loops );\r
-            ListUtil.assignIndexedSerial(this.morphPartList);\r
-\r
-            this.morphPartIt = this.morphPartList.iterator();\r
-            if(this.morphPartIt.hasNext()){\r
-                this.currentMorphPart = this.morphPartIt.next();\r
-            }\r
-        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){\r
-            // NOTHING\r
-        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){\r
-            // NOTHING\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage instanceof PmdMorphStage;\r
-\r
-        if(stage == PmdMorphHandler.MORPH_LIST){\r
-            if(this.morphPartIt.hasNext()){\r
-                this.currentMorphPart = this.morphPartIt.next();\r
-            }\r
-        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){\r
-            // NOTHING\r
-        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){\r
-            // NOTHING\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage instanceof PmdMorphStage;\r
-        if(stage == PmdMorphHandler.MORPH_LIST){\r
-            // NOTHING\r
-        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){\r
-            // NOTHING\r
-        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){\r
-            // NOTHING\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param morphName {@inheritDoc}\r
-     * @param morphType {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMorphInfo(String morphName, byte morphType){\r
-        this.currentMorphPart.getMorphName().setPrimaryText(morphName);\r
-        MorphType type = MorphType.decode(morphType);\r
-        this.currentMorphPart.setMorphType(type);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param serialId {@inheritDoc}\r
-     * @param xPos {@inheritDoc}\r
-     * @param yPos {@inheritDoc}\r
-     * @param zPos {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMorphVertexInfo(int serialId,\r
-                                   float xPos, float yPos, float zPos){\r
-        MorphVertex morphVertex;\r
-        morphVertex = new MorphVertex();\r
-        Pos3d position = morphVertex.getOffset();\r
-        position.setXPos(xPos);\r
-        position.setYPos(yPos);\r
-        position.setZPos(zPos);\r
-\r
-        Vertex vertex;\r
-        if(this.currentMorphPart.getMorphType().isBase()){\r
-            vertex = this.vertexList.get(serialId);\r
-            this.morphVertexList.add(vertex);\r
-        }else{\r
-            vertex = this.morphVertexList.get(serialId);\r
-        }\r
-        morphVertex.setBaseVertex(vertex);\r
-\r
-        this.currentMorphPart.getMorphVertexList().add(morphVertex);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param morphId {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdMorphOrderInfo(int morphId){\r
-        MorphPart part = this.morphPartList.get(morphId);\r
-        MorphType type = part.getMorphType();\r
-\r
-        List<MorphPart> partList = this.morphMap.get(type);\r
-        if(partList == null){\r
-            partList = new LinkedList<MorphPart>();\r
-            this.morphMap.put(type, partList);\r
-        }\r
-        partList.add(part);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building morph information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdMorphHandler;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.MorphType;
+import jp.sourceforge.mikutoga.pmd.MorphVertex;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Vertex;
+
+/**
+ * モーフ関係の通知をパーサから受け取る。
+ */
+class MorphBuilder implements PmdMorphHandler {
+
+    private final Map<MorphType, List<MorphPart>> morphMap;
+
+    private List<MorphPart> morphPartList;
+    private Iterator<MorphPart> morphPartIt;
+    private MorphPart currentMorphPart;
+    private final List<Vertex> vertexList;
+
+    private final List<Vertex> morphVertexList = new ArrayList<Vertex>();
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    MorphBuilder(PmdModel model){
+        super();
+        this.vertexList = model.getVertexList();
+        this.morphMap = model.getMorphMap();
+        return;
+    }
+
+    /**
+     * PMDファイル中の出現順で各モーフを格納するためのリストを設定する。
+     * 主な用途はモーフ英名との突き合わせ作業。
+     * @param list モーフ格納リスト
+     */
+    void setMorphPartList(List<MorphPart> list){
+        this.morphPartList = list;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage instanceof PmdMorphStage;
+
+        if(stage == PmdMorphHandler.MORPH_LIST){
+            ListUtil.prepareDefConsList(this.morphPartList,
+                                        MorphPart.class,
+                                        loops );
+            ListUtil.assignIndexedSerial(this.morphPartList);
+
+            this.morphPartIt = this.morphPartList.iterator();
+            if(this.morphPartIt.hasNext()){
+                this.currentMorphPart = this.morphPartIt.next();
+            }
+        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){
+            // NOTHING
+        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){
+            // NOTHING
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage instanceof PmdMorphStage;
+
+        if(stage == PmdMorphHandler.MORPH_LIST){
+            if(this.morphPartIt.hasNext()){
+                this.currentMorphPart = this.morphPartIt.next();
+            }
+        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){
+            // NOTHING
+        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){
+            // NOTHING
+        }
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage instanceof PmdMorphStage;
+        if(stage == PmdMorphHandler.MORPH_LIST){
+            // NOTHING
+        }else if(stage == PmdMorphHandler.MORPHVERTEX_LIST){
+            // NOTHING
+        }else if(stage == PmdMorphHandler.MORPHORDER_LIST){
+            // NOTHING
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param morphName {@inheritDoc}
+     * @param morphType {@inheritDoc}
+     */
+    @Override
+    public void pmdMorphInfo(String morphName, byte morphType){
+        this.currentMorphPart.getMorphName().setPrimaryText(morphName);
+        MorphType type = MorphType.decode(morphType);
+        this.currentMorphPart.setMorphType(type);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param serialId {@inheritDoc}
+     * @param xPos {@inheritDoc}
+     * @param yPos {@inheritDoc}
+     * @param zPos {@inheritDoc}
+     */
+    @Override
+    public void pmdMorphVertexInfo(int serialId,
+                                   float xPos, float yPos, float zPos){
+        MorphVertex morphVertex;
+        morphVertex = new MorphVertex();
+        Pos3d position = morphVertex.getOffset();
+        position.setXPos(xPos);
+        position.setYPos(yPos);
+        position.setZPos(zPos);
+
+        Vertex vertex;
+        if(this.currentMorphPart.getMorphType().isBase()){
+            vertex = this.vertexList.get(serialId);
+            this.morphVertexList.add(vertex);
+        }else{
+            vertex = this.morphVertexList.get(serialId);
+        }
+        morphVertex.setBaseVertex(vertex);
+
+        this.currentMorphPart.getMorphVertexList().add(morphVertex);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param morphId {@inheritDoc}
+     */
+    @Override
+    public void pmdMorphOrderInfo(int morphId){
+        MorphPart part = this.morphPartList.get(morphId);
+        MorphType type = part.getMorphType();
+
+        List<MorphPart> partList = this.morphMap.get(type);
+        if(partList == null){
+            partList = new LinkedList<MorphPart>();
+            this.morphMap.put(type, partList);
+        }
+        partList.add(part);
+
+        return;
+    }
+
+}
index 0b0c87b..1c4b0eb 100644 (file)
-/*\r
- * PMD file loader\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.io.IOException;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdParser;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-\r
-/**\r
- * PMDモデルファイルを読み込むためのローダ。\r
- */\r
-public class PmdLoader {\r
-\r
-    private PmdModel model;\r
-    private PmdParser parser;\r
-    private TextBuilder textBuilder;\r
-\r
-    private boolean loaded = false;\r
-    private boolean hasMoreData = false;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param source PMDファイル入力ソース\r
-     */\r
-    public PmdLoader(MmdSource source){\r
-        super();\r
-\r
-        this.model = new PmdModel();\r
-        this.parser = new PmdParser(source);\r
-        this.textBuilder = new TextBuilder(this.model);\r
-\r
-        setHandler();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * パーサに各種ハンドラの設定を行う。\r
-     */\r
-    private void setHandler(){\r
-        ShapeBuilder    shapeBuilder    = new ShapeBuilder(this.model);\r
-        MaterialBuilder materialBuilder = new MaterialBuilder(this.model);\r
-        BoneBuilder     boneBuilder     = new BoneBuilder(this.model);\r
-        MorphBuilder    morphBuilder    = new MorphBuilder(this.model);\r
-        ToonBuilder     toonBuilder     = new ToonBuilder(this.model);\r
-        RigidBuilder    rigidBuilder    = new RigidBuilder(this.model);\r
-        JointBuilder    jointBuilder    = new JointBuilder(this.model);\r
-\r
-        this.parser.setBasicHandler(this.textBuilder);\r
-        this.parser.setShapeHandler(shapeBuilder);\r
-        this.parser.setMaterialHandler(materialBuilder);\r
-        this.parser.setBoneHandler(boneBuilder);\r
-        this.parser.setMorphHandler(morphBuilder);\r
-        this.parser.setEngHandler(this.textBuilder);\r
-        this.parser.setToonHandler(toonBuilder);\r
-        this.parser.setRigidHandler(rigidBuilder);\r
-        this.parser.setJointHandler(jointBuilder);\r
-\r
-        List<MorphPart> morphPartList = new ArrayList<MorphPart>();\r
-        morphBuilder.setMorphPartList(morphPartList);\r
-        this.textBuilder.setMorphPartList(morphPartList);\r
-        morphPartList.clear();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイルの読み込みを行いモデル情報を返す。\r
-     * 1インスタンスにつき一度しかロードできない。\r
-     * @return モデル情報\r
-     * @throws IOException 入力エラー\r
-     * @throws MmdFormatException PMDファイルフォーマットの異常を検出\r
-     * @throws IllegalStateException このインスタンスで再度のロードを試みた。\r
-     */\r
-    public PmdModel load()\r
-            throws IOException,\r
-                   MmdFormatException,\r
-                   IllegalStateException {\r
-        if(this.loaded) throw new IllegalStateException();\r
-\r
-        PmdModel result;\r
-        try{\r
-            this.parser.parsePmd();\r
-        }finally{\r
-            this.loaded = true;\r
-\r
-            result = this.model;\r
-            this.hasMoreData = this.textBuilder.hasMoreData();\r
-\r
-            this.model = null;\r
-            this.parser = null;\r
-            this.textBuilder = null;\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * ロード処理が正常終了したのにまだ読み込んでいない部分が放置されているか判定する。\r
-     * MMDでの仕様拡張によるPMDファイルフォーマットの拡張が行われた場合を想定。\r
-     * @return 読み込んでいない部分があればtrue\r
-     */\r
-    public boolean hasMoreData(){\r
-        return this.hasMoreData;\r
-    }\r
-\r
-}\r
+/*
+ * PMD file loader
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+import jp.sourceforge.mikutoga.parser.pmd.PmdParser;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+
+/**
+ * PMDモデルファイルを読み込むためのローダ。
+ */
+public class PmdLoader {
+
+    private PmdModel model;
+    private PmdParser parser;
+    private TextBuilder textBuilder;
+
+    private boolean loaded = false;
+    private boolean hasMoreData = false;
+
+    /**
+     * コンストラクタ。
+     * @param source PMDファイル入力ソース
+     */
+    public PmdLoader(MmdSource source){
+        super();
+
+        this.model = new PmdModel();
+        this.parser = new PmdParser(source);
+        this.textBuilder = new TextBuilder(this.model);
+
+        setHandler();
+
+        return;
+    }
+
+    /**
+     * パーサに各種ハンドラの設定を行う。
+     */
+    private void setHandler(){
+        ShapeBuilder    shapeBuilder    = new ShapeBuilder(this.model);
+        MaterialBuilder materialBuilder = new MaterialBuilder(this.model);
+        BoneBuilder     boneBuilder     = new BoneBuilder(this.model);
+        MorphBuilder    morphBuilder    = new MorphBuilder(this.model);
+        ToonBuilder     toonBuilder     = new ToonBuilder(this.model);
+        RigidBuilder    rigidBuilder    = new RigidBuilder(this.model);
+        JointBuilder    jointBuilder    = new JointBuilder(this.model);
+
+        this.parser.setBasicHandler(this.textBuilder);
+        this.parser.setShapeHandler(shapeBuilder);
+        this.parser.setMaterialHandler(materialBuilder);
+        this.parser.setBoneHandler(boneBuilder);
+        this.parser.setMorphHandler(morphBuilder);
+        this.parser.setEngHandler(this.textBuilder);
+        this.parser.setToonHandler(toonBuilder);
+        this.parser.setRigidHandler(rigidBuilder);
+        this.parser.setJointHandler(jointBuilder);
+
+        List<MorphPart> morphPartList = new ArrayList<MorphPart>();
+        morphBuilder.setMorphPartList(morphPartList);
+        this.textBuilder.setMorphPartList(morphPartList);
+        morphPartList.clear();
+
+        return;
+    }
+
+    /**
+     * PMDファイルの読み込みを行いモデル情報を返す。
+     * 1インスタンスにつき一度しかロードできない。
+     * @return モデル情報
+     * @throws IOException 入力エラー
+     * @throws MmdFormatException PMDファイルフォーマットの異常を検出
+     * @throws IllegalStateException このインスタンスで再度のロードを試みた。
+     */
+    public PmdModel load()
+            throws IOException,
+                   MmdFormatException,
+                   IllegalStateException {
+        if(this.loaded) throw new IllegalStateException();
+
+        PmdModel result;
+        try{
+            this.parser.parsePmd();
+        }finally{
+            this.loaded = true;
+
+            result = this.model;
+            this.hasMoreData = this.textBuilder.hasMoreData();
+
+            this.model = null;
+            this.parser = null;
+            this.textBuilder = null;
+        }
+
+        return result;
+    }
+
+    /**
+     * ロード処理が正常終了したのにまだ読み込んでいない部分が放置されているか判定する。
+     * MMDでの仕様拡張によるPMDファイルフォーマットの拡張が行われた場合を想定。
+     * @return 読み込んでいない部分があればtrue
+     */
+    public boolean hasMoreData(){
+        return this.hasMoreData;
+    }
+
+}
index a255fdc..e952e17 100644 (file)
-/*\r
- * building rigid information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdRigidHandler;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.DynamicsInfo;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Rad3d;\r
-import jp.sourceforge.mikutoga.pmd.RigidBehaviorType;\r
-import jp.sourceforge.mikutoga.pmd.RigidGroup;\r
-import jp.sourceforge.mikutoga.pmd.RigidInfo;\r
-import jp.sourceforge.mikutoga.pmd.RigidShape;\r
-import jp.sourceforge.mikutoga.pmd.RigidShapeType;\r
-\r
-/**\r
- * 剛体関係の通知をパーサから受け取る。\r
- */\r
-class RigidBuilder implements PmdRigidHandler {\r
-\r
-    private final List<BoneInfo> boneList;\r
-\r
-    private final List<RigidInfo> rigidList;\r
-    private Iterator<RigidInfo> rigidIt;\r
-    private RigidInfo currentRigid = null;\r
-\r
-    private final List<RigidGroup> rigidGroupList;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    RigidBuilder(PmdModel model){\r
-        super();\r
-        this.boneList = model.getBoneList();\r
-        this.rigidList = model.getRigidList();\r
-        this.rigidGroupList = model.getRigidGroupList();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        ListUtil.prepareDefConsList(this.rigidList, RigidInfo.class, loops);\r
-        ListUtil.assignIndexedSerial(this.rigidList);\r
-\r
-        this.rigidIt = this.rigidList.iterator();\r
-        if(this.rigidIt.hasNext()){\r
-            this.currentRigid = this.rigidIt.next();\r
-        }\r
-\r
-        ListUtil.prepareDefConsList(this.rigidGroupList,\r
-                                    RigidGroup.class,\r
-                                    PmdLimits.RIGIDGROUP_FIXEDNUM );\r
-        ListUtil.assignIndexedSerial(this.rigidGroupList);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        if(this.rigidIt.hasNext()){\r
-            this.currentRigid = this.rigidIt.next();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param rigidName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidName(String rigidName){\r
-        this.currentRigid.getRigidName().setPrimaryText(rigidName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param rigidGroupId {@inheritDoc}\r
-     * @param linkedBoneId {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidInfo(int rigidGroupId, int linkedBoneId){\r
-        BoneInfo bone;\r
-        if(linkedBoneId < 0 || 65535 <= linkedBoneId){\r
-            bone = null;\r
-        }else{\r
-            bone = this.boneList.get(linkedBoneId);\r
-        }\r
-        RigidGroup group = this.rigidGroupList.get(rigidGroupId);\r
-\r
-        this.currentRigid.setLinkedBone(bone);\r
-        this.currentRigid.setRigidGroup(group);\r
-        group.getRigidList().add(this.currentRigid);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param shapeType {@inheritDoc}\r
-     * @param width {@inheritDoc}\r
-     * @param height {@inheritDoc}\r
-     * @param depth {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidShape(byte shapeType,\r
-                              float width, float height, float depth){\r
-        RigidShape shape = this.currentRigid.getRigidShape();\r
-\r
-        shape.setWidth(width);\r
-        shape.setHeight(height);\r
-        shape.setDepth(depth);\r
-\r
-        RigidShapeType type = RigidShapeType.decode(shapeType);\r
-        shape.setShapeType(type);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param posX {@inheritDoc}\r
-     * @param posY {@inheritDoc}\r
-     * @param posZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidPosition(float posX, float posY, float posZ){\r
-        Pos3d position = this.currentRigid.getPosition();\r
-        position.setXPos(posX);\r
-        position.setYPos(posY);\r
-        position.setZPos(posZ);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param radX {@inheritDoc}\r
-     * @param radY {@inheritDoc}\r
-     * @param radZ {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidRotation(float radX, float radY, float radZ){\r
-        Rad3d rotation = this.currentRigid.getRotation();\r
-        rotation.setXRad(radX);\r
-        rotation.setYRad(radY);\r
-        rotation.setZRad(radZ);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param mass {@inheritDoc}\r
-     * @param dampingPos {@inheritDoc}\r
-     * @param dampingRot {@inheritDoc}\r
-     * @param restitution {@inheritDoc}\r
-     * @param friction {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidPhysics(float mass,\r
-                                  float dampingPos,\r
-                                  float dampingRot,\r
-                                  float restitution,\r
-                                  float friction ){\r
-        DynamicsInfo info = this.currentRigid.getDynamicsInfo();\r
-\r
-        info.setMass(mass);\r
-        info.setDampingPosition(dampingPos);\r
-        info.setDampingRotation(dampingRot);\r
-        info.setRestitution(restitution);\r
-        info.setFriction(friction);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param behaveType {@inheritDoc}\r
-     * @param collisionMap {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdRigidBehavior(byte behaveType, short collisionMap){\r
-        RigidBehaviorType type = RigidBehaviorType.decode(behaveType);\r
-        this.currentRigid.setBehaviorType(type);\r
-\r
-        for(int bitPos = 0; bitPos < PmdLimits.RIGIDGROUP_FIXEDNUM; bitPos++){\r
-            short mask = 0x0001;\r
-            mask <<= bitPos;\r
-            if((collisionMap & mask) == 0){\r
-                RigidGroup group = this.rigidGroupList.get(bitPos);\r
-                this.currentRigid.getThroughGroupColl().add(group);\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building rigid information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.parser.pmd.PmdRigidHandler;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.DynamicsInfo;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Rad3d;
+import jp.sourceforge.mikutoga.pmd.RigidBehaviorType;
+import jp.sourceforge.mikutoga.pmd.RigidGroup;
+import jp.sourceforge.mikutoga.pmd.RigidInfo;
+import jp.sourceforge.mikutoga.pmd.RigidShape;
+import jp.sourceforge.mikutoga.pmd.RigidShapeType;
+
+/**
+ * 剛体関係の通知をパーサから受け取る。
+ */
+class RigidBuilder implements PmdRigidHandler {
+
+    private final List<BoneInfo> boneList;
+
+    private final List<RigidInfo> rigidList;
+    private Iterator<RigidInfo> rigidIt;
+    private RigidInfo currentRigid = null;
+
+    private final List<RigidGroup> rigidGroupList;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    RigidBuilder(PmdModel model){
+        super();
+        this.boneList = model.getBoneList();
+        this.rigidList = model.getRigidList();
+        this.rigidGroupList = model.getRigidGroupList();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        ListUtil.prepareDefConsList(this.rigidList, RigidInfo.class, loops);
+        ListUtil.assignIndexedSerial(this.rigidList);
+
+        this.rigidIt = this.rigidList.iterator();
+        if(this.rigidIt.hasNext()){
+            this.currentRigid = this.rigidIt.next();
+        }
+
+        ListUtil.prepareDefConsList(this.rigidGroupList,
+                                    RigidGroup.class,
+                                    PmdLimits.RIGIDGROUP_FIXEDNUM );
+        ListUtil.assignIndexedSerial(this.rigidGroupList);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        if(this.rigidIt.hasNext()){
+            this.currentRigid = this.rigidIt.next();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param rigidName {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidName(String rigidName){
+        this.currentRigid.getRigidName().setPrimaryText(rigidName);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param rigidGroupId {@inheritDoc}
+     * @param linkedBoneId {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidInfo(int rigidGroupId, int linkedBoneId){
+        BoneInfo bone;
+        if(linkedBoneId < 0 || 65535 <= linkedBoneId){
+            bone = null;
+        }else{
+            bone = this.boneList.get(linkedBoneId);
+        }
+        RigidGroup group = this.rigidGroupList.get(rigidGroupId);
+
+        this.currentRigid.setLinkedBone(bone);
+        this.currentRigid.setRigidGroup(group);
+        group.getRigidList().add(this.currentRigid);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param shapeType {@inheritDoc}
+     * @param width {@inheritDoc}
+     * @param height {@inheritDoc}
+     * @param depth {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidShape(byte shapeType,
+                              float width, float height, float depth){
+        RigidShape shape = this.currentRigid.getRigidShape();
+
+        shape.setWidth(width);
+        shape.setHeight(height);
+        shape.setDepth(depth);
+
+        RigidShapeType type = RigidShapeType.decode(shapeType);
+        shape.setShapeType(type);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param posX {@inheritDoc}
+     * @param posY {@inheritDoc}
+     * @param posZ {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidPosition(float posX, float posY, float posZ){
+        Pos3d position = this.currentRigid.getPosition();
+        position.setXPos(posX);
+        position.setYPos(posY);
+        position.setZPos(posZ);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param radX {@inheritDoc}
+     * @param radY {@inheritDoc}
+     * @param radZ {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidRotation(float radX, float radY, float radZ){
+        Rad3d rotation = this.currentRigid.getRotation();
+        rotation.setXRad(radX);
+        rotation.setYRad(radY);
+        rotation.setZRad(radZ);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param mass {@inheritDoc}
+     * @param dampingPos {@inheritDoc}
+     * @param dampingRot {@inheritDoc}
+     * @param restitution {@inheritDoc}
+     * @param friction {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidPhysics(float mass,
+                                  float dampingPos,
+                                  float dampingRot,
+                                  float restitution,
+                                  float friction ){
+        DynamicsInfo info = this.currentRigid.getDynamicsInfo();
+
+        info.setMass(mass);
+        info.setDampingPosition(dampingPos);
+        info.setDampingRotation(dampingRot);
+        info.setRestitution(restitution);
+        info.setFriction(friction);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param behaveType {@inheritDoc}
+     * @param collisionMap {@inheritDoc}
+     */
+    @Override
+    public void pmdRigidBehavior(byte behaveType, short collisionMap){
+        RigidBehaviorType type = RigidBehaviorType.decode(behaveType);
+        this.currentRigid.setBehaviorType(type);
+
+        for(int bitPos = 0; bitPos < PmdLimits.RIGIDGROUP_FIXEDNUM; bitPos++){
+            short mask = 0x0001;
+            mask <<= bitPos;
+            if((collisionMap & mask) == 0){
+                RigidGroup group = this.rigidGroupList.get(bitPos);
+                this.currentRigid.getThroughGroupColl().add(group);
+            }
+        }
+
+        return;
+    }
+
+}
index b42388f..32ee115 100644 (file)
-/*\r
- * building shape information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.RandomAccess;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdShapeHandler;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos2d;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Surface;\r
-import jp.sourceforge.mikutoga.pmd.Vec3d;\r
-import jp.sourceforge.mikutoga.pmd.Vertex;\r
-\r
-/**\r
- * モデル形状に関する通知をパーサから受け取る。\r
- */\r
-class ShapeBuilder implements PmdShapeHandler {\r
-\r
-    private final List<Vertex> vertexList;\r
-    private final List<BoneInfo> boneList;\r
-    private final List<Surface> surfaceList;\r
-\r
-    private Iterator<Vertex> vertexIt;\r
-    private Vertex currentVertex = null;\r
-\r
-    private Iterator<Surface> surfaceIt;\r
-    private Surface currentSurface = null;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    ShapeBuilder(PmdModel model){\r
-        super();\r
-\r
-        this.vertexList  = model.getVertexList();\r
-        this.boneList    = model.getBoneList();\r
-        this.surfaceList = model.getSurfaceList();\r
-\r
-        assert this.vertexList instanceof RandomAccess;\r
-        assert this.surfaceList instanceof RandomAccess;\r
-        assert this.boneList instanceof RandomAccess;\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ボーンリスト上にボーンを用意する。\r
-     * すでに指定位置にボーンがあればなにもしない。\r
-     * @param id 0から始まるボーン番号\r
-     * @return 用意されたボーン\r
-     */\r
-    private BoneInfo prepareBone(int id){\r
-        ListUtil.extendCollection(this.boneList, id + 1);\r
-        BoneInfo bone = this.boneList.get(id);\r
-        if(bone == null){\r
-            bone = new BoneInfo();\r
-            bone.setSerialNumber(id);\r
-            this.boneList.set(id, bone);\r
-        }\r
-        return bone;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        if(stage == PmdShapeHandler.VERTEX_LIST){\r
-            ListUtil.prepareDefConsList(this.vertexList, Vertex.class, loops);\r
-            ListUtil.assignIndexedSerial(this.vertexList);\r
-\r
-            this.vertexIt = this.vertexList.iterator();\r
-            if(this.vertexIt.hasNext()){\r
-                this.currentVertex = this.vertexIt.next();\r
-            }\r
-        }else if(stage == PmdShapeHandler.SURFACE_LIST){\r
-            ListUtil.prepareDefConsList(this.surfaceList,\r
-                                        Surface.class, loops );\r
-            ListUtil.assignIndexedSerial(this.surfaceList);\r
-\r
-            this.surfaceIt = this.surfaceList.iterator();\r
-            if(this.surfaceIt.hasNext()){\r
-                this.currentSurface = this.surfaceIt.next();\r
-            }\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        if(stage == PmdShapeHandler.VERTEX_LIST){\r
-            if(this.vertexIt.hasNext()){\r
-                this.currentVertex = this.vertexIt.next();\r
-            }\r
-        }else if(stage == PmdShapeHandler.SURFACE_LIST){\r
-            if(this.surfaceIt.hasNext()){\r
-                this.currentSurface = this.surfaceIt.next();\r
-            }\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param xPos {@inheritDoc}\r
-     * @param yPos {@inheritDoc}\r
-     * @param zPos {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdVertexPosition(float xPos, float yPos, float zPos){\r
-        Pos3d position = this.currentVertex.getPosition();\r
-        position.setXPos(xPos);\r
-        position.setYPos(yPos);\r
-        position.setZPos(zPos);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param xVec {@inheritDoc}\r
-     * @param yVec {@inheritDoc}\r
-     * @param zVec {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdVertexNormal(float xVec, float yVec, float zVec){\r
-        Vec3d normal = this.currentVertex.getNormal();\r
-        normal.setXVal(xVec);\r
-        normal.setYVal(yVec);\r
-        normal.setZVal(zVec);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param uVal {@inheritDoc}\r
-     * @param vVal {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdVertexUV(float uVal, float vVal){\r
-        Pos2d uv = this.currentVertex.getUVPosition();\r
-        uv.setXPos(uVal);\r
-        uv.setYPos(vVal);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param boneId1 {@inheritDoc}\r
-     * @param boneId2 {@inheritDoc}\r
-     * @param weightForB1 {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdVertexWeight(int boneId1, int boneId2, int weightForB1){\r
-        BoneInfo bone1 = prepareBone(boneId1);\r
-        BoneInfo bone2 = prepareBone(boneId2);\r
-\r
-        this.currentVertex.setBonePair(bone1, bone2);\r
-        this.currentVertex.setWeightA(weightForB1);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param hideEdge {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdVertexEdge(boolean hideEdge){\r
-        this.currentVertex.setEdgeAppearance( ! hideEdge );\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param vertexId1 {@inheritDoc}\r
-     * @param vertexId2 {@inheritDoc}\r
-     * @param vertexId3 {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdSurfaceTriangle(int vertexId1,\r
-                                      int vertexId2,\r
-                                      int vertexId3 ){\r
-        Vertex vtx1 = this.vertexList.get(vertexId1);\r
-        Vertex vtx2 = this.vertexList.get(vertexId2);\r
-        Vertex vtx3 = this.vertexList.get(vertexId3);\r
-\r
-        this.currentSurface.setTriangle(vtx1, vtx2, vtx3);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building shape information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.RandomAccess;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdShapeHandler;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos2d;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Surface;
+import jp.sourceforge.mikutoga.pmd.Vec3d;
+import jp.sourceforge.mikutoga.pmd.Vertex;
+
+/**
+ * モデル形状に関する通知をパーサから受け取る。
+ */
+class ShapeBuilder implements PmdShapeHandler {
+
+    private final List<Vertex> vertexList;
+    private final List<BoneInfo> boneList;
+    private final List<Surface> surfaceList;
+
+    private Iterator<Vertex> vertexIt;
+    private Vertex currentVertex = null;
+
+    private Iterator<Surface> surfaceIt;
+    private Surface currentSurface = null;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    ShapeBuilder(PmdModel model){
+        super();
+
+        this.vertexList  = model.getVertexList();
+        this.boneList    = model.getBoneList();
+        this.surfaceList = model.getSurfaceList();
+
+        assert this.vertexList instanceof RandomAccess;
+        assert this.surfaceList instanceof RandomAccess;
+        assert this.boneList instanceof RandomAccess;
+
+        return;
+    }
+
+    /**
+     * ボーンリスト上にボーンを用意する。
+     * すでに指定位置にボーンがあればなにもしない。
+     * @param id 0から始まるボーン番号
+     * @return 用意されたボーン
+     */
+    private BoneInfo prepareBone(int id){
+        ListUtil.extendCollection(this.boneList, id + 1);
+        BoneInfo bone = this.boneList.get(id);
+        if(bone == null){
+            bone = new BoneInfo();
+            bone.setSerialNumber(id);
+            this.boneList.set(id, bone);
+        }
+        return bone;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        if(stage == PmdShapeHandler.VERTEX_LIST){
+            ListUtil.prepareDefConsList(this.vertexList, Vertex.class, loops);
+            ListUtil.assignIndexedSerial(this.vertexList);
+
+            this.vertexIt = this.vertexList.iterator();
+            if(this.vertexIt.hasNext()){
+                this.currentVertex = this.vertexIt.next();
+            }
+        }else if(stage == PmdShapeHandler.SURFACE_LIST){
+            ListUtil.prepareDefConsList(this.surfaceList,
+                                        Surface.class, loops );
+            ListUtil.assignIndexedSerial(this.surfaceList);
+
+            this.surfaceIt = this.surfaceList.iterator();
+            if(this.surfaceIt.hasNext()){
+                this.currentSurface = this.surfaceIt.next();
+            }
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        if(stage == PmdShapeHandler.VERTEX_LIST){
+            if(this.vertexIt.hasNext()){
+                this.currentVertex = this.vertexIt.next();
+            }
+        }else if(stage == PmdShapeHandler.SURFACE_LIST){
+            if(this.surfaceIt.hasNext()){
+                this.currentSurface = this.surfaceIt.next();
+            }
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param xPos {@inheritDoc}
+     * @param yPos {@inheritDoc}
+     * @param zPos {@inheritDoc}
+     */
+    @Override
+    public void pmdVertexPosition(float xPos, float yPos, float zPos){
+        Pos3d position = this.currentVertex.getPosition();
+        position.setXPos(xPos);
+        position.setYPos(yPos);
+        position.setZPos(zPos);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param xVec {@inheritDoc}
+     * @param yVec {@inheritDoc}
+     * @param zVec {@inheritDoc}
+     */
+    @Override
+    public void pmdVertexNormal(float xVec, float yVec, float zVec){
+        Vec3d normal = this.currentVertex.getNormal();
+        normal.setXVal(xVec);
+        normal.setYVal(yVec);
+        normal.setZVal(zVec);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param uVal {@inheritDoc}
+     * @param vVal {@inheritDoc}
+     */
+    @Override
+    public void pmdVertexUV(float uVal, float vVal){
+        Pos2d uv = this.currentVertex.getUVPosition();
+        uv.setXPos(uVal);
+        uv.setYPos(vVal);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param boneId1 {@inheritDoc}
+     * @param boneId2 {@inheritDoc}
+     * @param weightForB1 {@inheritDoc}
+     */
+    @Override
+    public void pmdVertexWeight(int boneId1, int boneId2, int weightForB1){
+        BoneInfo bone1 = prepareBone(boneId1);
+        BoneInfo bone2 = prepareBone(boneId2);
+
+        this.currentVertex.setBonePair(bone1, bone2);
+        this.currentVertex.setWeightA(weightForB1);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param hideEdge {@inheritDoc}
+     */
+    @Override
+    public void pmdVertexEdge(boolean hideEdge){
+        this.currentVertex.setEdgeAppearance( ! hideEdge );
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param vertexId1 {@inheritDoc}
+     * @param vertexId2 {@inheritDoc}
+     * @param vertexId3 {@inheritDoc}
+     */
+    @Override
+    public void pmdSurfaceTriangle(int vertexId1,
+                                      int vertexId2,
+                                      int vertexId3 ){
+        Vertex vtx1 = this.vertexList.get(vertexId1);
+        Vertex vtx2 = this.vertexList.get(vertexId2);
+        Vertex vtx3 = this.vertexList.get(vertexId3);
+
+        this.currentSurface.setTriangle(vtx1, vtx2, vtx3);
+
+        return;
+    }
+
+}
index e34f621..e37082f 100644 (file)
-/*\r
- * building text info\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdBasicHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdEngHandler;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-\r
-/**\r
- * テキスト関係の通知をパーサから受け取る。\r
- */\r
-class TextBuilder implements PmdBasicHandler, PmdEngHandler {\r
-\r
-    private final PmdModel model;\r
-\r
-    private final I18nText modelName;\r
-    private final I18nText description;\r
-\r
-    private final List<BoneInfo> boneList;\r
-    private Iterator<BoneInfo> boneIt;\r
-    private BoneInfo currentBone = null;\r
-\r
-    private List<MorphPart> morphPartList;\r
-    private Iterator<MorphPart> morphPartIt;\r
-    private MorphPart currentMorphPart = null;\r
-\r
-    private final List<BoneGroup> boneGroupList;\r
-    private Iterator<BoneGroup> boneGroupIt;\r
-    private BoneGroup currentBoneGroup = null;\r
-\r
-    private boolean hasMoreData = false;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    TextBuilder(PmdModel model){\r
-        super();\r
-\r
-        this.model = model;\r
-\r
-        this.modelName   = model.getModelName();\r
-        this.description = model.getDescription();\r
-\r
-        this.boneList      = model.getBoneList();\r
-        this.boneGroupList = model.getBoneGroupList();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * PMDファイル中の出現順で各モーフを格納するためのリストを設定する。\r
-     * 主な用途はモーフ和英名の突き合わせ作業。\r
-     * @param list モーフ格納リスト\r
-     */\r
-    void setMorphPartList(List<MorphPart> list){\r
-        this.morphPartList = list;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdParseStart(){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param hasMoreData {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdParseEnd(boolean hasMoreData){\r
-        this.hasMoreData = hasMoreData;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage instanceof PmdEngStage;\r
-\r
-        if(stage == PmdEngHandler.ENGBONE_LIST){\r
-            this.boneIt = this.boneList.iterator();\r
-            if(this.boneIt.hasNext()){\r
-                this.currentBone = this.boneIt.next();\r
-            }\r
-        }else if(stage == PmdEngHandler.ENGMORPH_LIST){\r
-            this.morphPartIt = this.morphPartList.iterator();\r
-\r
-            // 「base」モーフを読み飛ばす\r
-            assert this.morphPartIt.hasNext();\r
-            MorphPart part = this.morphPartIt.next();\r
-            assert part != null;\r
-\r
-            if(this.morphPartIt.hasNext()){\r
-                this.currentMorphPart = this.morphPartIt.next();\r
-            }\r
-        }else if(stage == PmdEngHandler.ENGBONEGROUP_LIST){\r
-            this.boneGroupIt = this.boneGroupList.iterator();\r
-\r
-            // デフォルトボーングループを読み飛ばす\r
-            assert this.boneGroupIt.hasNext();\r
-            BoneGroup group = this.boneGroupIt.next();\r
-            assert group != null;\r
-\r
-            if(this.boneGroupIt.hasNext()){\r
-                this.currentBoneGroup = this.boneGroupIt.next();\r
-            }\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage instanceof PmdEngStage;\r
-\r
-        if(stage == PmdEngHandler.ENGBONE_LIST){\r
-            if(this.boneIt.hasNext()){\r
-                this.currentBone = this.boneIt.next();\r
-            }\r
-        }else if(stage == PmdEngHandler.ENGMORPH_LIST){\r
-            if(this.morphPartIt.hasNext()){\r
-                this.currentMorphPart = this.morphPartIt.next();\r
-            }\r
-        }else if(stage == PmdEngHandler.ENGBONEGROUP_LIST){\r
-            if(this.boneGroupIt.hasNext()){\r
-                this.currentBoneGroup = this.boneGroupIt.next();\r
-            }\r
-        }else{\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage instanceof PmdEngStage;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param ver {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdHeaderInfo(float ver){\r
-        this.model.setHeaderVersion(ver);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param modelName {@inheritDoc}\r
-     * @param description {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdModelInfo(String modelName, String description){\r
-        this.modelName  .setPrimaryText(modelName);\r
-        this.description.setPrimaryText(description);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param hasEnglishInfo {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdEngEnabled(boolean hasEnglishInfo){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param modelName {@inheritDoc}\r
-     * @param description {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdEngModelInfo(String modelName, String description){\r
-        this.modelName  .setGlobalText(modelName);\r
-        this.description.setGlobalText(description);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param boneName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdEngBoneInfo(String boneName){\r
-        this.currentBone.getBoneName().setGlobalText(boneName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param morphName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdEngMorphInfo(String morphName){\r
-        this.currentMorphPart.getMorphName().setGlobalText(morphName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param groupName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdEngBoneGroupInfo(String groupName){\r
-        this.currentBoneGroup.getGroupName().setGlobalText(groupName);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 読み残したデータがあるか判定する。\r
-     * @return 読み残したデータがあればtrue\r
-     */\r
-    public boolean hasMoreData(){\r
-        return this.hasMoreData;\r
-    }\r
-\r
-}\r
+/*
+ * building text info
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdBasicHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdEngHandler;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+
+/**
+ * テキスト関係の通知をパーサから受け取る。
+ */
+class TextBuilder implements PmdBasicHandler, PmdEngHandler {
+
+    private final PmdModel model;
+
+    private final I18nText modelName;
+    private final I18nText description;
+
+    private final List<BoneInfo> boneList;
+    private Iterator<BoneInfo> boneIt;
+    private BoneInfo currentBone = null;
+
+    private List<MorphPart> morphPartList;
+    private Iterator<MorphPart> morphPartIt;
+    private MorphPart currentMorphPart = null;
+
+    private final List<BoneGroup> boneGroupList;
+    private Iterator<BoneGroup> boneGroupIt;
+    private BoneGroup currentBoneGroup = null;
+
+    private boolean hasMoreData = false;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    TextBuilder(PmdModel model){
+        super();
+
+        this.model = model;
+
+        this.modelName   = model.getModelName();
+        this.description = model.getDescription();
+
+        this.boneList      = model.getBoneList();
+        this.boneGroupList = model.getBoneGroupList();
+
+        return;
+    }
+
+    /**
+     * PMDファイル中の出現順で各モーフを格納するためのリストを設定する。
+     * 主な用途はモーフ和英名の突き合わせ作業。
+     * @param list モーフ格納リスト
+     */
+    void setMorphPartList(List<MorphPart> list){
+        this.morphPartList = list;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void pmdParseStart(){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param hasMoreData {@inheritDoc}
+     */
+    @Override
+    public void pmdParseEnd(boolean hasMoreData){
+        this.hasMoreData = hasMoreData;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage instanceof PmdEngStage;
+
+        if(stage == PmdEngHandler.ENGBONE_LIST){
+            this.boneIt = this.boneList.iterator();
+            if(this.boneIt.hasNext()){
+                this.currentBone = this.boneIt.next();
+            }
+        }else if(stage == PmdEngHandler.ENGMORPH_LIST){
+            this.morphPartIt = this.morphPartList.iterator();
+
+            // 「base」モーフを読み飛ばす
+            assert this.morphPartIt.hasNext();
+            MorphPart part = this.morphPartIt.next();
+            assert part != null;
+
+            if(this.morphPartIt.hasNext()){
+                this.currentMorphPart = this.morphPartIt.next();
+            }
+        }else if(stage == PmdEngHandler.ENGBONEGROUP_LIST){
+            this.boneGroupIt = this.boneGroupList.iterator();
+
+            // デフォルトボーングループを読み飛ばす
+            assert this.boneGroupIt.hasNext();
+            BoneGroup group = this.boneGroupIt.next();
+            assert group != null;
+
+            if(this.boneGroupIt.hasNext()){
+                this.currentBoneGroup = this.boneGroupIt.next();
+            }
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage instanceof PmdEngStage;
+
+        if(stage == PmdEngHandler.ENGBONE_LIST){
+            if(this.boneIt.hasNext()){
+                this.currentBone = this.boneIt.next();
+            }
+        }else if(stage == PmdEngHandler.ENGMORPH_LIST){
+            if(this.morphPartIt.hasNext()){
+                this.currentMorphPart = this.morphPartIt.next();
+            }
+        }else if(stage == PmdEngHandler.ENGBONEGROUP_LIST){
+            if(this.boneGroupIt.hasNext()){
+                this.currentBoneGroup = this.boneGroupIt.next();
+            }
+        }else{
+            assert false;
+            throw new AssertionError();
+        }
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage instanceof PmdEngStage;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param ver {@inheritDoc}
+     */
+    @Override
+    public void pmdHeaderInfo(float ver){
+        this.model.setHeaderVersion(ver);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param modelName {@inheritDoc}
+     * @param description {@inheritDoc}
+     */
+    @Override
+    public void pmdModelInfo(String modelName, String description){
+        this.modelName  .setPrimaryText(modelName);
+        this.description.setPrimaryText(description);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param hasEnglishInfo {@inheritDoc}
+     */
+    @Override
+    public void pmdEngEnabled(boolean hasEnglishInfo){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param modelName {@inheritDoc}
+     * @param description {@inheritDoc}
+     */
+    @Override
+    public void pmdEngModelInfo(String modelName, String description){
+        this.modelName  .setGlobalText(modelName);
+        this.description.setGlobalText(description);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param boneName {@inheritDoc}
+     */
+    @Override
+    public void pmdEngBoneInfo(String boneName){
+        this.currentBone.getBoneName().setGlobalText(boneName);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param morphName {@inheritDoc}
+     */
+    @Override
+    public void pmdEngMorphInfo(String morphName){
+        this.currentMorphPart.getMorphName().setGlobalText(morphName);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param groupName {@inheritDoc}
+     */
+    @Override
+    public void pmdEngBoneGroupInfo(String groupName){
+        this.currentBoneGroup.getGroupName().setGlobalText(groupName);
+        return;
+    }
+
+    /**
+     * 読み残したデータがあるか判定する。
+     * @return 読み残したデータがあればtrue
+     */
+    public boolean hasMoreData(){
+        return this.hasMoreData;
+    }
+
+}
index f4a28e1..b859942 100644 (file)
@@ -1,83 +1,83 @@
-/*\r
- * building toon information\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdToonHandler;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.ToonMap;\r
-\r
-/**\r
- * トゥーン関係の通知をパーサから受け取る。\r
- */\r
-class ToonBuilder implements PmdToonHandler {\r
-\r
-    private final PmdModel model;\r
-\r
-    private ToonMap toonMap;\r
-    private int index;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param model モデル\r
-     */\r
-    ToonBuilder(PmdModel model){\r
-        this.model = model;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     * @param loops {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopStart(ParseStage stage, int loops){\r
-        assert stage == PmdToonHandler.TOON_LIST;\r
-        assert loops == PmdLimits.TOON_FIXEDNUM;\r
-\r
-        this.toonMap = new ToonMap();\r
-        this.index = 0;\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopNext(ParseStage stage){\r
-        assert stage == PmdToonHandler.TOON_LIST;\r
-        this.index++;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param stage {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void loopEnd(ParseStage stage){\r
-        assert stage == PmdToonHandler.TOON_LIST;\r
-        this.model.setToonMap(this.toonMap);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param toonFileName {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void pmdToonFileInfo(String toonFileName){\r
-        this.toonMap.setIndexedToon(this.index, toonFileName);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * building toon information
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdLimits;
+import jp.sourceforge.mikutoga.parser.pmd.PmdToonHandler;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.ToonMap;
+
+/**
+ * トゥーン関係の通知をパーサから受け取る。
+ */
+class ToonBuilder implements PmdToonHandler {
+
+    private final PmdModel model;
+
+    private ToonMap toonMap;
+    private int index;
+
+    /**
+     * コンストラクタ。
+     * @param model モデル
+     */
+    ToonBuilder(PmdModel model){
+        this.model = model;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     * @param loops {@inheritDoc}
+     */
+    @Override
+    public void loopStart(ParseStage stage, int loops){
+        assert stage == PmdToonHandler.TOON_LIST;
+        assert loops == PmdLimits.TOON_FIXEDNUM;
+
+        this.toonMap = new ToonMap();
+        this.index = 0;
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopNext(ParseStage stage){
+        assert stage == PmdToonHandler.TOON_LIST;
+        this.index++;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param stage {@inheritDoc}
+     */
+    @Override
+    public void loopEnd(ParseStage stage){
+        assert stage == PmdToonHandler.TOON_LIST;
+        this.model.setToonMap(this.toonMap);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param toonFileName {@inheritDoc}
+     */
+    @Override
+    public void pmdToonFileInfo(String toonFileName){
+        this.toonMap.setIndexedToon(this.index, toonFileName);
+        return;
+    }
+
+}
index c1f0ca6..3d9a418 100644 (file)
@@ -1,15 +1,15 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * PMDモデルファイルをパースし、\r
- * 内容を反映したオブジェクト群を構築するためのライブラリ。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.pmdloader;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * PMDモデルファイルをパースし、
+ * 内容を反映したオブジェクト群を構築するためのライブラリ。
+ */
+
+package jp.sourceforge.mikutoga.pmd.pmdloader;
+
+/* EOF */
index 65100b4..4e682c5 100644 (file)
-/*\r
- * pmd-xml exporter\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.xml;\r
-\r
-import java.awt.Color;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.util.List;\r
-import java.util.Map;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.SerialNumbered;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.BoneType;\r
-import jp.sourceforge.mikutoga.pmd.Deg3d;\r
-import jp.sourceforge.mikutoga.pmd.DynamicsInfo;\r
-import jp.sourceforge.mikutoga.pmd.IKChain;\r
-import jp.sourceforge.mikutoga.pmd.JointInfo;\r
-import jp.sourceforge.mikutoga.pmd.Material;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.MorphType;\r
-import jp.sourceforge.mikutoga.pmd.MorphVertex;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos2d;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Rad3d;\r
-import jp.sourceforge.mikutoga.pmd.RigidGroup;\r
-import jp.sourceforge.mikutoga.pmd.RigidInfo;\r
-import jp.sourceforge.mikutoga.pmd.RigidShape;\r
-import jp.sourceforge.mikutoga.pmd.RigidShapeType;\r
-import jp.sourceforge.mikutoga.pmd.ShadeInfo;\r
-import jp.sourceforge.mikutoga.pmd.Surface;\r
-import jp.sourceforge.mikutoga.pmd.ToonMap;\r
-import jp.sourceforge.mikutoga.pmd.TripletRange;\r
-import jp.sourceforge.mikutoga.pmd.Vec3d;\r
-import jp.sourceforge.mikutoga.pmd.Vertex;\r
-import jp.sourceforge.mikutoga.xml.BasicXmlExporter;\r
-import jp.sourceforge.mikutoga.xml.XmlResourceResolver;\r
-\r
-/**\r
- * XML形式でPMDモデルデータを出力する。\r
- */\r
-public class PmdXmlExporter extends BasicXmlExporter{\r
-\r
-    private static final String TOP_COMMENT =\r
-            "  MikuMikuDance\n    model-data(*.pmd) on XML";\r
-    private static final String SCHEMA_LOCATION =\r
-            PmdXmlResources.NS_PMDXML + " " + PmdXmlResources.SCHEMA_PMDXML;\r
-\r
-    /** 改行文字列 CR。 */\r
-    private static final String CR = "\r";       // 0x0d\r
-    /** 改行文字列 LF。 */\r
-    private static final String LF = "\n";       // 0x0a\r
-    /** 改行文字列 CRLF。 */\r
-    private static final String CRLF = CR + LF;  // 0x0d, 0x0a\r
-\r
-    private static final String PFX_SURFACEGROUP = "sg";\r
-    private static final String PFX_TOONFILE = "tf";\r
-    private static final String PFX_VERTEX = "vtx";\r
-    private static final String PFX_BONE = "bn";\r
-    private static final String PFX_RIGID = "rd";\r
-    private static final String PFX_RIGIDGROUP = "rg";\r
-\r
-    private static final String BONETYPE_COMMENT =\r
-          "Bone types:\n"\r
-        + "[0 : ROTATE      : Rotate       : 回転           :]\n"\r
-        + "[1 : ROTMOV      : Rotate/Move  : 回転/移動      :]\n"\r
-        + "[2 : IK          : IK           : IK             :]\n"\r
-        + "[3 : UNKNOWN     : Unknown      : 不明           :]\n"\r
-        + "[4 : UNDERIK     : Under IK     : IK影響下(回転) :]\n"\r
-        + "[5 : UNDERROT    : Under rotate : 回転影響下     :]\n"\r
-        + "[6 : IKCONNECTED : IK connected : IK接続先       :]\n"\r
-        + "[7 : HIDDEN      : Hidden       : 非表示         :]\n"\r
-        + "[8 : TWIST       : Twist        : 捩り           :]\n"\r
-        + "[9 : LINKEDROT   : Linked Rotate: 回転連動       :]\n";\r
-\r
-    private static final String MORPHTYPE_COMMENT =\r
-          "Morph types:\n"\r
-        + "[1 : EYEBROW : まゆ   ]\n"\r
-        + "[2 : EYE     : 目     ]\n"\r
-        + "[3 : LIP     : リップ ]\n"\r
-        + "[4 : EXTRA   : その他 ]\n";\r
-\r
-    private static final String RIGIDBEHAVIOR_COMMENT =\r
-          "Rigid behavior types:\n"\r
-        + "[0 : FOLLOWBONE    : ボーン追従       ]\n"\r
-        + "[1 : ONLYDYNAMICS  : 物理演算         ]\n"\r
-        + "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";\r
-\r
-    private String generator = "";\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * 文字エンコーディングはUTF-8が用いられる。\r
-     * @param stream 出力ストリーム\r
-     */\r
-    public PmdXmlExporter(OutputStream stream){\r
-        super(stream);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Generatorメタ情報を設定する。\r
-     * @param generatorArg Generatorメタ情報\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setGenerator(String generatorArg)\r
-            throws NullPointerException{\r
-        if(generatorArg == null) throw new NullPointerException();\r
-        this.generator = generatorArg;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 任意の文字列がBasicLatin文字のみから構成されるか判定する。\r
-     * @param seq 文字列\r
-     * @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue\r
-     */\r
-    public static boolean hasOnlyBasicLatin(CharSequence seq){\r
-        if(seq == null) return true;\r
-        int length = seq.length();\r
-        for(int pos = 0; pos < length; pos++){\r
-            char ch = seq.charAt(pos);\r
-            if(ch > 0x007f) return false;\r
-        }\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     * @throws IOException {@inheritDoc}\r
-     */\r
-    @Override\r
-    public PmdXmlExporter ind() throws IOException{\r
-        super.ind();\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 文字参照によるエスケープを補佐するためのコメントを出力する。\r
-     * @param seq 文字列\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putUnescapedComment(CharSequence seq)\r
-            throws IOException{\r
-        if( ! isBasicLatinOnlyOut() ) return this;\r
-        if(hasOnlyBasicLatin(seq)) return this;\r
-        put(' ').putLineComment(seq);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 多言語化された各種識別名を出力する。\r
-     * プライマリ名は出力対象外。\r
-     * @param text 多言語文字列\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putI18nName(I18nText text) throws IOException{\r
-        for(String lang639 : text.lang639CodeList()){\r
-            if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;\r
-            String name = text.getText(lang639);\r
-            ind().put("<i18nName ");\r
-            putAttr("lang", lang639).put(' ');\r
-            putAttr("name", name);\r
-            put(" />");\r
-            putUnescapedComment(name);\r
-            ln();\r
-        }\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 番号付けされたID(IDREF)属性を出力する。\r
-     * @param attrName 属性名\r
-     * @param prefix IDプレフィクス\r
-     * @param num 番号\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,\r
-                                                 CharSequence prefix,\r
-                                                 int num )\r
-            throws IOException{\r
-        put(attrName).put("=\"");\r
-        put(prefix).put(num);\r
-        put('"');\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 番号付けされたID(IDREF)属性を出力する。\r
-     * @param attrName 属性名\r
-     * @param prefix IDプレフィクス\r
-     * @param numbered 番号付けされたオブジェクト\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,\r
-                                                 CharSequence prefix,\r
-                                                 SerialNumbered numbered )\r
-            throws IOException{\r
-        putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 位置情報を出力する。\r
-     * @param position 位置情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putPosition(Pos3d position) throws IOException{\r
-        put("<position ");\r
-        putFloatAttr("x", position.getXPos()).put(' ');\r
-        putFloatAttr("y", position.getYPos()).put(' ');\r
-        putFloatAttr("z", position.getZPos()).put(' ');\r
-        put("/>");\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 姿勢情報(ラジアン)を出力する。\r
-     * @param rotation 姿勢情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putRadRotation(Rad3d rotation)\r
-            throws IOException{\r
-        put("<radRotation ");\r
-        putFloatAttr("xRad", rotation.getXRad()).put(' ');\r
-        putFloatAttr("yRad", rotation.getYRad()).put(' ');\r
-        putFloatAttr("zRad", rotation.getZRad()).put(' ');\r
-        put("/>");\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 多言語識別名属性のローカルな名前をコメント出力する。\r
-     * @param name 多言語識別名\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putLocalNameComment(I18nText name)\r
-            throws IOException{\r
-        String localName = name.getText();\r
-        ind().putLineComment(localName);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 多言語識別名属性のプライマリな名前を出力する。\r
-     * @param attrName 属性名\r
-     * @param name 多言語識別名\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected PmdXmlExporter putPrimaryNameAttr(CharSequence attrName,\r
-                                                   I18nText name)\r
-            throws IOException{\r
-        String primaryName = name.getPrimaryText();\r
-        putAttr(attrName, primaryName);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * PMDモデルデータをXML形式で出力する。\r
-     * @param model PMDモデルデータ\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public void putPmdModel(PmdModel model) throws IOException{\r
-        ind().put("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").ln(2);\r
-\r
-        ind().putBlockComment(TOP_COMMENT).ln(2);\r
-\r
-        /*\r
-        ind().put("<!DOCTYPE pmdModel").ln();\r
-        ind().put(" SYSTEM \"")\r
-             .put(PmdXmlResources.DTD_PMDXML)\r
-             .put("\" >")\r
-             .ln(3);\r
-         */\r
-\r
-        I18nText modelName = model.getModelName();\r
-        ind().putLocalNameComment(modelName).ln();\r
-        ind().put("<pmdModel").ln();\r
-        pushNest();\r
-        ind().putAttr("xmlns", PmdXmlResources.NS_PMDXML).ln();\r
-        ind().putAttr("xmlns:xsi", XmlResourceResolver.NS_XSD).ln();\r
-        ind().putAttr("xsi:schemaLocation", SCHEMA_LOCATION).ln();\r
-        ind().putAttr("schemaVersion", PmdXmlResources.VER_PMDXML).ln(2);\r
-        ind().putPrimaryNameAttr("name", modelName).ln();\r
-        popNest();\r
-        put(">").ln(2);\r
-\r
-        putModelInfo(model).flush();\r
-        putMetaInfo(model).flush();\r
-        putMaterialList(model).flush();\r
-        putToonMap(model).flush();\r
-        putBoneList(model).flush();\r
-        putBoneGroupList(model).flush();\r
-        putIKChainList(model).flush();\r
-        putMorphList(model).flush();\r
-        putRigidList(model).flush();\r
-        putRigidGroupList(model).flush();\r
-        putJointList(model).flush();\r
-        putSurfaceGroupList(model).flush();\r
-        putVertexList(model).flush();\r
-\r
-        ind().put("</pmdModel>").ln(2);\r
-        ind().put("<!-- EOF -->").ln();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * モデル基本情報を出力する。\r
-     * @param model モデル情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putModelInfo(PmdModel model)\r
-            throws IOException{\r
-        I18nText modelName = model.getModelName();\r
-        putI18nName(modelName);\r
-        ln();\r
-\r
-        I18nText description = model.getDescription();\r
-        for(String lang639 : description.lang639CodeList()){\r
-            String descText = description.getText(lang639);\r
-            putDescription(lang639, descText);\r
-            ln();\r
-        }\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * モデル詳細テキストを出力する。\r
-     * @param lang639 言語コード\r
-     * @param content 詳細内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putDescription(CharSequence lang639,\r
-                                              CharSequence content)\r
-            throws IOException{\r
-        String text = content.toString();\r
-        text = text.replace(CRLF, LF);\r
-        text = text.replace(CR,   LF);\r
-\r
-        ind().put("<description");\r
-        if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){\r
-            put(" ");\r
-            putAttr("lang", lang639);\r
-        }\r
-        put(">").ln();\r
-\r
-        putBRedContent(text);\r
-\r
-        ln();\r
-        ind().put("</description>").ln();\r
-\r
-        if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){\r
-            putBlockComment(text);\r
-        }\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * break要素を含む要素内容を出力する。\r
-     * 必要に応じてXML定義済み実体文字が割り振られた文字、\r
-     * コントロールコード、および非BasicLatin文字がエスケープされる。\r
-     * \nはbrタグに変換される。\r
-     * @param content 内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    protected BasicXmlExporter putBRedContent(CharSequence content)\r
-            throws IOException{\r
-        int length = content.length();\r
-\r
-        for(int pos = 0; pos < length; pos++){\r
-            char ch = content.charAt(pos);\r
-            if(ch == '\n'){\r
-                put("<br/>").ln();\r
-            }else if(Character.isISOControl(ch)){\r
-                putCharRef2Hex(ch);\r
-            }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){\r
-                putCharRef4Hex(ch);\r
-            }else{\r
-                switch(ch){\r
-                case '&':  put("&amp;");  break;\r
-                case '<':  put("&lt;");   break;\r
-                case '>':  put("&gt;");   break;\r
-                case '"':  put("&quot;"); break;\r
-                case '\'': put("&apos;"); break;\r
-                default:   put(ch);       break;\r
-                }\r
-            }\r
-        }\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 各種メタ情報を出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putMetaInfo(PmdModel model) throws IOException{\r
-        ind().put("<license>").ln();\r
-        ind().put("</license>").ln(2);\r
-\r
-        ind().put("<credits>").ln();\r
-        ind().put("</credits>").ln(2);\r
-\r
-        ind().put("<meta ");\r
-        putAttr("name", "generator").put(' ')\r
-                                    .putAttr("content", this.generator);\r
-        put(" />").ln();\r
-        ind().put("<meta ");\r
-        putAttr("name", "siteURL").put(' ').putAttr("content", "");\r
-        put(" />").ln();\r
-        ind().put("<meta ");\r
-        putAttr("name", "imageURL").put(' ').putAttr("content", "");\r
-        put(" />").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * マテリアル素材一覧を出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putMaterialList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<materialList>").ln(2);\r
-        pushNest();\r
-\r
-        int ct = 0;\r
-        for(Material material : model.getMaterialList()){\r
-            putMaterial(material, ct++);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</materialList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * マテリアル素材情報を出力する。\r
-     * @param material マテリアル素材\r
-     * @param no マテリアル通し番号\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putMaterial(Material material, int no)\r
-            throws IOException{\r
-        String bool;\r
-        if(material.getEdgeAppearance()) bool = "true";\r
-        else                             bool = "false";\r
-        I18nText name = material.getMaterialName();\r
-        String primary = name.getPrimaryText();\r
-        String local = name.getText();\r
-\r
-        if(local != null && local.length() > 0){\r
-            ind().putLineComment(local).ln();\r
-        }\r
-        ind().put("<material ");\r
-        if(primary != null && primary.length() > 0){\r
-            putAttr("name", primary).put(' ');\r
-        }\r
-\r
-        putAttr("showEdge", bool);\r
-        put(" ");\r
-        putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);\r
-        put('>').ln();\r
-        pushNest();\r
-\r
-        putI18nName(name);\r
-\r
-        float[] rgba = new float[4];\r
-\r
-        Color diffuse = material.getDiffuseColor();\r
-        diffuse.getRGBComponents(rgba);\r
-        ind().put("<diffuse ");\r
-        putFloatAttr("r", rgba[0]).put(' ');\r
-        putFloatAttr("g", rgba[1]).put(' ');\r
-        putFloatAttr("b", rgba[2]).put(' ');\r
-        putFloatAttr("alpha", rgba[3]).put(' ');\r
-        put("/>").ln();\r
-\r
-        Color specular = material.getSpecularColor();\r
-        specular.getRGBComponents(rgba);\r
-        float shininess = material.getShininess();\r
-        ind().put("<specular ");\r
-        putFloatAttr("r", rgba[0]).put(' ');\r
-        putFloatAttr("g", rgba[1]).put(' ');\r
-        putFloatAttr("b", rgba[2]).put(' ');\r
-        putFloatAttr("shininess", shininess).put(' ');\r
-        put("/>").ln();\r
-\r
-        Color ambient = material.getAmbientColor();\r
-        ambient.getRGBComponents(rgba);\r
-        ind().put("<ambient ");\r
-        putFloatAttr("r", rgba[0]).put(' ');\r
-        putFloatAttr("g", rgba[1]).put(' ');\r
-        putFloatAttr("b", rgba[2]).put(' ');\r
-        put("/>").ln();\r
-\r
-        ShadeInfo shade = material.getShadeInfo();\r
-        String textureFileName = shade.getTextureFileName();\r
-        String spheremapFileName = shade.getSpheremapFileName();\r
-\r
-        if(shade.isValidToonIndex()){\r
-            ind().put("<toon ");\r
-            int toonIdx = shade.getToonIndex();\r
-            putNumberedIdAttr("toonFileIdRef", PFX_TOONFILE, toonIdx);\r
-            put(" />");\r
-            String toonFileName = shade.getToonFileName();\r
-            if(toonFileName != null && toonFileName.length() > 0){\r
-                put(' ').putLineComment(toonFileName);\r
-            }\r
-            ln();\r
-        }\r
-\r
-        if(textureFileName != null && textureFileName.length() > 0){\r
-            ind().put("<textureFile ");\r
-            putAttr("winFileName", textureFileName);\r
-            put(" />").ln();\r
-        }\r
-\r
-        if(spheremapFileName != null && spheremapFileName.length() > 0){\r
-            ind().put("<spheremapFile ");\r
-            putAttr("winFileName", spheremapFileName);\r
-            put(" />").ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</material>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * トゥーンファイルマッピング情報を出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putToonMap(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<toonMap>").ln();\r
-        pushNest();\r
-\r
-        ToonMap map = model.getToonMap();\r
-        for(int index = 0; index <= 9; index++){\r
-            ind().putToon(map, index).ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</toonMap>").ln(2);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のトゥーンファイル情報を出力する。\r
-     * @param map トゥーンマップ\r
-     * @param index インデックス値\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putToon(ToonMap map, int index)\r
-            throws IOException{\r
-        put("<toonDef ");\r
-        putNumberedIdAttr("toonFileId", PFX_TOONFILE, index).put(' ');\r
-        putIntAttr("index", index).put(' ');\r
-        String toonFile = map.getIndexedToon(index);\r
-        putAttr("winFileName", toonFile);\r
-        put(" />");\r
-        putUnescapedComment(toonFile);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * サーフェイスグループリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putSurfaceGroupList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<surfaceGroupList>").ln(2);\r
-        pushNest();\r
-\r
-        int ct = 0;\r
-        for(Material material : model.getMaterialList()){\r
-            List<Surface> surfaceList = material.getSurfaceList();\r
-            putSurfaceList(surfaceList, ct++);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</surfaceGroupList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のサーフェイスグループを出力する。\r
-     * @param surfaceList サーフェイスのリスト\r
-     * @param index グループインデックス\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putSurfaceList(List<Surface> surfaceList,\r
-                                              int index)\r
-            throws IOException{\r
-        ind().put("<surfaceGroup ");\r
-        putNumberedIdAttr("surfaceGroupId", PFX_SURFACEGROUP, index);\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        for(Surface surface : surfaceList){\r
-            putSurface(surface);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</surfaceGroup>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のサーフェイスを出力する。\r
-     * @param surface サーフェイス\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putSurface(Surface surface)\r
-            throws IOException{\r
-        ind().put("<surface ");\r
-\r
-        Vertex vertex1 = surface.getVertex1();\r
-        Vertex vertex2 = surface.getVertex2();\r
-        Vertex vertex3 = surface.getVertex3();\r
-\r
-        putNumberedIdAttr("vtxIdRef1", PFX_VERTEX, vertex1).put(' ');\r
-        putNumberedIdAttr("vtxIdRef2", PFX_VERTEX, vertex2).put(' ');\r
-        putNumberedIdAttr("vtxIdRef3", PFX_VERTEX, vertex3).put(' ');\r
-\r
-        put("/>").ln();\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 頂点リストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putVertexList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<vertexList>").ln(2);\r
-        pushNest();\r
-\r
-        for(Vertex vertex : model.getVertexList()){\r
-            putVertex(vertex);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</vertexList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別の頂点情報を出力する。\r
-     * @param vertex 頂点\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putVertex(Vertex vertex)\r
-            throws IOException{\r
-        String bool;\r
-        if(vertex.getEdgeAppearance()) bool = "true";\r
-        else                           bool = "false";\r
-\r
-        ind().put("<vertex ");\r
-        putNumberedIdAttr("vtxId", PFX_VERTEX, vertex).put(' ');\r
-        putAttr("showEdge", bool);\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        Pos3d position = vertex.getPosition();\r
-        ind().putPosition(position).ln();\r
-\r
-        Vec3d normal = vertex.getNormal();\r
-        ind().put("<normal ");\r
-        putFloatAttr("x", normal.getXVal()).put(' ');\r
-        putFloatAttr("y", normal.getYVal()).put(' ');\r
-        putFloatAttr("z", normal.getZVal()).put(' ');\r
-        put("/>").ln();\r
-\r
-        Pos2d uvPos = vertex.getUVPosition();\r
-        ind().put("<uvMap ");\r
-        putFloatAttr("u", uvPos.getXPos()).put(' ');\r
-        putFloatAttr("v", uvPos.getYPos()).put(' ');\r
-        put("/>").ln();\r
-\r
-        BoneInfo boneA = vertex.getBoneA();\r
-        BoneInfo boneB = vertex.getBoneB();\r
-        int weight = vertex.getWeightA();\r
-        ind().put("<skinning ");\r
-        putNumberedIdAttr("boneIdRef1", PFX_BONE, boneA).put(' ');\r
-        putNumberedIdAttr("boneIdRef2", PFX_BONE, boneB).put(' ');\r
-        putIntAttr("weightBalance", weight).put(' ');\r
-        put("/>").ln();\r
-\r
-        popNest();\r
-        ind().put("</vertex>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * ボーンリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putBoneList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<boneList>").ln(2);\r
-        pushNest();\r
-\r
-        putBlockComment(BONETYPE_COMMENT).ln();\r
-\r
-        for(BoneInfo bone : model.getBoneList()){\r
-            putBone(bone);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</boneList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のボーン情報を出力する。\r
-     * @param bone ボーン情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putBone(BoneInfo bone)\r
-            throws IOException{\r
-        I18nText i18nName = bone.getBoneName();\r
-        BoneType type = bone.getBoneType();\r
-\r
-        putLocalNameComment(i18nName).putLineComment(type.getGuiName()).ln();\r
-        ind().put("<bone ");\r
-        putPrimaryNameAttr("name", i18nName).put(' ');\r
-        putNumberedIdAttr("boneId", PFX_BONE, bone).put(' ');\r
-        putAttr("type", type.name());\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        putI18nName(i18nName);\r
-\r
-        Pos3d position = bone.getPosition();\r
-        ind().putPosition(position).ln();\r
-\r
-        BoneInfo ikBone = bone.getIKBone();\r
-        if(bone.getBoneType() == BoneType.LINKEDROT){\r
-            ind().put("<rotationRatio ");\r
-            putIntAttr("ratio", bone.getRotationRatio());\r
-            put(" />").ln();\r
-        }else if(ikBone != null){\r
-            ind().put("<ikBone ");\r
-            putNumberedIdAttr("boneIdRef", PFX_BONE, ikBone);\r
-            put(" /> ");\r
-            String ikBoneName = "Ref:" + ikBone.getBoneName().getText();\r
-            putLineComment(ikBoneName);\r
-            ln();\r
-        }\r
-\r
-        StringBuilder chainComment = new StringBuilder();\r
-        ind().put("<boneChain");\r
-        BoneInfo prev = bone.getPrevBone();\r
-        BoneInfo next = bone.getNextBone();\r
-        if(prev != null){\r
-            put(' ');\r
-            putNumberedIdAttr("prevBoneIdRef", PFX_BONE, prev);\r
-            chainComment.append('[')\r
-                        .append(prev.getBoneName().getPrimaryText())\r
-                        .append(']')\r
-                        .append("=> #");\r
-        }\r
-        if(next != null){\r
-            put(' ');\r
-            putNumberedIdAttr("nextBoneIdRef", PFX_BONE, next);\r
-            if(chainComment.length() <= 0) chainComment.append("#");\r
-            chainComment.append(" =>")\r
-                        .append('[')\r
-                        .append(next.getBoneName().getPrimaryText())\r
-                        .append(']');\r
-        }\r
-        put(" />").ln();\r
-        ind().putLineComment(chainComment).ln();\r
-\r
-        popNest();\r
-        ind().put("</bone>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * ボーングループリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putBoneGroupList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<boneGroupList>").ln(2);\r
-        pushNest();\r
-\r
-        for(BoneGroup group : model.getBoneGroupList()){\r
-            if(group.isDefaultBoneGroup()) continue;\r
-            putBoneGroup(group);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</boneGroupList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のボーングループ情報を出力する。\r
-     * @param group ボーングループ情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putBoneGroup(BoneGroup group)\r
-            throws IOException{\r
-        I18nText i18nName = group.getGroupName();\r
-\r
-        putLocalNameComment(i18nName).ln();\r
-        ind().put("<boneGroup ");\r
-        putPrimaryNameAttr("name", i18nName);\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        putI18nName(i18nName);\r
-\r
-        for(BoneInfo bone : group){\r
-            ind().put("<boneGroupMember ");\r
-            putNumberedIdAttr("boneIdRef", PFX_BONE, bone);\r
-            put(" /> ");\r
-            String boneName = "Ref:" + bone.getBoneName().getText();\r
-            putLineComment(boneName).ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</boneGroup>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * IKチェーンリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putIKChainList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<ikChainList>").ln(2);\r
-        pushNest();\r
-\r
-        for(IKChain chain : model.getIKChainList()){\r
-            putIKChain(chain);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</ikChainList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のIKチェーン情報を出力する。\r
-     * @param chain チェーン情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putIKChain(IKChain chain)\r
-            throws IOException{\r
-        int depth = chain.getIKDepth();\r
-        float weight = chain.getIKWeight();\r
-        BoneInfo ikBone = chain.getIkBone();\r
-\r
-        ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();\r
-        ind().put("<ikChain ");\r
-        putNumberedIdAttr("ikBoneIdRef", PFX_BONE, ikBone).put(' ');\r
-        putIntAttr("recursiveDepth", depth).put(' ');\r
-        putFloatAttr("weight", weight);\r
-        put("> ").ln();\r
-        pushNest();\r
-\r
-        for(BoneInfo bone : chain){\r
-            ind().put("<chainOrder ");\r
-            putNumberedIdAttr("boneIdRef", PFX_BONE, bone);\r
-            put(" /> ");\r
-            putLineComment("Ref:" + bone.getBoneName().getText());\r
-            ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</ikChain>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * モーフリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putMorphList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<morphList>").ln(2);\r
-        pushNest();\r
-\r
-        putBlockComment(MORPHTYPE_COMMENT).ln();\r
-\r
-        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();\r
-        for(MorphType type : MorphType.values()){\r
-            if(type == MorphType.BASE) continue;\r
-            List<MorphPart> partList = morphMap.get(type);\r
-            if(partList == null) continue;\r
-            for(MorphPart part : partList){\r
-                putMorphPart(part);\r
-            }\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</morphList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のモーフ情報を出力する。\r
-     * @param part モーフ情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putMorphPart(MorphPart part)\r
-            throws IOException{\r
-        I18nText i18nName = part.getMorphName();\r
-        String primary = i18nName.getPrimaryText();\r
-\r
-        ind().put("<morph ");\r
-        putAttr("name", primary).put(' ');\r
-        putAttr("type", part.getMorphType().name());\r
-        put(">");\r
-        putUnescapedComment(primary);\r
-        ln();\r
-        pushNest();\r
-\r
-        putI18nName(i18nName);\r
-\r
-        for(MorphVertex mvertex : part){\r
-            Pos3d offset = mvertex.getOffset();\r
-            Vertex base = mvertex.getBaseVertex();\r
-\r
-            ind().put("<morphVertex ");\r
-            putNumberedIdAttr("vtxIdRef", PFX_VERTEX, base).put(' ');\r
-            putFloatAttr("xOff", offset.getXPos()).put(' ');\r
-            putFloatAttr("yOff", offset.getYPos()).put(' ');\r
-            putFloatAttr("zOff", offset.getZPos()).put(' ');\r
-            put("/>");\r
-            ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</morph>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 剛体リストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putRigidList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<rigidList>").ln(2);\r
-        pushNest();\r
-\r
-        putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();\r
-\r
-        for(RigidInfo rigid : model.getRigidList()){\r
-            putRigid(rigid);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</rigidList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別の剛体情報を出力する。\r
-     * @param rigid 剛体情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putRigid(RigidInfo rigid)\r
-            throws IOException{\r
-        BoneInfo linkedBone = rigid.getLinkedBone();\r
-        I18nText i18nName = rigid.getRigidName();\r
-        String primary = i18nName.getPrimaryText();\r
-\r
-        putLocalNameComment(i18nName).ln();\r
-        ind().put("<rigid ");\r
-        putAttr("name", primary).put(' ');\r
-        putNumberedIdAttr("rigidId", PFX_RIGID, rigid).put(' ');\r
-        putAttr("behavior", rigid.getBehaviorType().name());\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        putI18nName(i18nName);\r
-\r
-        if(linkedBone != null){\r
-            ind().put("<linkedBone ");\r
-            putNumberedIdAttr("boneIdRef", PFX_BONE, linkedBone);\r
-            put(" /> ");\r
-            putLineComment("Ref:" + linkedBone.getBoneName().getText());\r
-            ln(2);\r
-        }\r
-\r
-        RigidShape shape = rigid.getRigidShape();\r
-        putRigidShape(shape);\r
-\r
-        Pos3d position = rigid.getPosition();\r
-        ind().putPosition(position).ln();\r
-\r
-        Rad3d rotation = rigid.getRotation();\r
-        ind().putRadRotation(rotation).ln();\r
-\r
-        DynamicsInfo dynamics = rigid.getDynamicsInfo();\r
-        putDynamics(dynamics).ln();\r
-\r
-        for(RigidGroup group : rigid.getThroughGroupColl()){\r
-            ind().put("<throughRigidGroup ");\r
-            putNumberedIdAttr("rigidGroupIdRef",\r
-                              PFX_RIGIDGROUP,\r
-                              group.getSerialNumber() + 1).put(' ');\r
-            put(" />").ln();\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</rigid>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 剛体形状を出力する。\r
-     * @param shape 剛体形状\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putRigidShape(RigidShape shape)\r
-            throws IOException{\r
-        RigidShapeType type = shape.getShapeType();\r
-\r
-        switch(type){\r
-        case BOX:\r
-            ind().put("<rigidShapeBox ");\r
-            putFloatAttr("width", shape.getWidth()).put(' ');\r
-            putFloatAttr("height", shape.getHeight()).put(' ');\r
-            putFloatAttr("depth", shape.getDepth()).put(' ');\r
-            break;\r
-        case SPHERE:\r
-            ind().put("<rigidShapeSphere ");\r
-            putFloatAttr("radius", shape.getRadius()).put(' ');\r
-            break;\r
-        case CAPSULE:\r
-            ind().put("<rigidShapeCapsule ");\r
-            putFloatAttr("height", shape.getHeight()).put(' ');\r
-            putFloatAttr("radius", shape.getRadius()).put(' ');\r
-            break;\r
-        default:\r
-            assert false;\r
-            throw new AssertionError();\r
-        }\r
-\r
-        put("/>").ln();\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 力学設定を出力する。\r
-     * @param dynamics 力学設定\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putDynamics(DynamicsInfo dynamics)\r
-            throws IOException{\r
-        ind().put("<dynamics").ln();\r
-        pushNest();\r
-        ind().putFloatAttr("mass", dynamics.getMass()).ln();\r
-        ind().putFloatAttr("dampingPosition",\r
-                dynamics.getDampingPosition()).ln();\r
-        ind().putFloatAttr("dampingRotation",\r
-                dynamics.getDampingRotation()).ln();\r
-        ind().putFloatAttr("restitution", dynamics.getRestitution()).ln();\r
-        ind().putFloatAttr("friction", dynamics.getFriction()).ln();\r
-        popNest();\r
-        ind().put("/>").ln();\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 剛体グループリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putRigidGroupList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<rigidGroupList>").ln(2);\r
-        pushNest();\r
-\r
-        for(RigidGroup group : model.getRigidGroupList()){\r
-            ind().put("<rigidGroup ");\r
-            putNumberedIdAttr("rigidGroupId",\r
-                              PFX_RIGIDGROUP,\r
-                              group.getSerialNumber() + 1);\r
-            List<RigidInfo> rigidList = group.getRigidList();\r
-            if(rigidList.size() <= 0){\r
-                put(" />").ln(2);\r
-                continue;\r
-            }\r
-            put(">").ln();\r
-            pushNest();\r
-\r
-            for(RigidInfo rigid : rigidList){\r
-                ind().put("<rigidGroupMember ");\r
-                putNumberedIdAttr("rigidIdRef", PFX_RIGID, rigid).put(' ');\r
-                put("/>");\r
-                put(' ');\r
-                putLineComment("Ref:" + rigid.getRigidName().getText());\r
-                ln();\r
-            }\r
-\r
-            popNest();\r
-            ind().put("</rigidGroup>").ln(2);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</rigidGroupList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * ジョイントリストを出力する。\r
-     * @param model モデルデータ\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putJointList(PmdModel model)\r
-            throws IOException{\r
-        ind().put("<jointList>").ln(2);\r
-        pushNest();\r
-\r
-        for(JointInfo joint : model.getJointList()){\r
-            putJoint(joint);\r
-        }\r
-\r
-        popNest();\r
-        ind().put("</jointList>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 個別のジョイント情報を出力する。\r
-     * @param joint ジョイント情報\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    private PmdXmlExporter putJoint(JointInfo joint)\r
-            throws IOException{\r
-        I18nText i18nName = joint.getJointName();\r
-\r
-        putLocalNameComment(i18nName).ln();\r
-        ind().put("<joint ");\r
-        putPrimaryNameAttr("name", i18nName);\r
-        put(">").ln();\r
-        pushNest();\r
-\r
-        putI18nName(i18nName);\r
-\r
-        RigidInfo rigidA = joint.getRigidA();\r
-        RigidInfo rigidB = joint.getRigidB();\r
-        ind().put("<jointedRigidPair ");\r
-        putNumberedIdAttr("rigidIdRef1", PFX_RIGID, rigidA).put(' ');\r
-        putNumberedIdAttr("rigidIdRef2", PFX_RIGID, rigidB).put(' ');\r
-        put("/>").ln();\r
-        ind();\r
-        putLineComment("[" + rigidA.getRigidName().getText() + "]"\r
-                + " <=> [" + rigidB.getRigidName().getText() + "]");\r
-        ln(2);\r
-\r
-        Pos3d position = joint.getPosition();\r
-        ind().putPosition(position).ln();\r
-\r
-        TripletRange posRange = joint.getPositionRange();\r
-        ind().put("<limitPosition").ln();\r
-        pushNest();\r
-        ind();\r
-        putFloatAttr("xFrom", posRange.getXFrom()).put(' ');\r
-        putFloatAttr("xTo",   posRange.getXTo()).ln();\r
-        ind();\r
-        putFloatAttr("yFrom", posRange.getYFrom()).put(' ');\r
-        putFloatAttr("yTo",   posRange.getYTo()).ln();\r
-        ind();\r
-        putFloatAttr("zFrom", posRange.getZFrom()).put(' ');\r
-        putFloatAttr("zTo",   posRange.getZTo()).ln();\r
-        popNest();\r
-        ind().put("/>").ln(2);\r
-\r
-        Rad3d rotation = joint.getRotation();\r
-        ind().putRadRotation(rotation).ln();\r
-        TripletRange rotRange = joint.getRotationRange();\r
-        ind().put("<limitRotation").ln();\r
-        pushNest();\r
-        ind();\r
-        putFloatAttr("xFrom", rotRange.getXFrom()).put(' ');\r
-        putFloatAttr("xTo",   rotRange.getXTo()).ln();\r
-        ind();\r
-        putFloatAttr("yFrom", rotRange.getYFrom()).put(' ');\r
-        putFloatAttr("yTo",   rotRange.getYTo()).ln();\r
-        ind();\r
-        putFloatAttr("zFrom", rotRange.getZFrom()).put(' ');\r
-        putFloatAttr("zTo",   rotRange.getZTo()).ln();\r
-        popNest();\r
-        ind().put("/>").ln(2);\r
-\r
-        Pos3d elaPosition = joint.getElasticPosition();\r
-        ind().put("<elasticPosition ");\r
-        putFloatAttr("x", elaPosition.getXPos()).put(' ');\r
-        putFloatAttr("y", elaPosition.getYPos()).put(' ');\r
-        putFloatAttr("z", elaPosition.getZPos()).put(' ');\r
-        put("/>").ln();\r
-\r
-        Deg3d elaRotation = joint.getElasticRotation();\r
-        ind().put("<elasticRotation ");\r
-        putFloatAttr("xDeg", elaRotation.getXDeg()).put(' ');\r
-        putFloatAttr("yDeg", elaRotation.getYDeg()).put(' ');\r
-        putFloatAttr("zDeg", elaRotation.getZDeg()).put(' ');\r
-        put("/>").ln(2);\r
-\r
-        popNest();\r
-        ind().put("</joint>").ln(2);\r
-\r
-        return this;\r
-    }\r
-\r
-}\r
+/*
+ * pmd-xml exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.xml;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.SerialNumbered;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.BoneType;
+import jp.sourceforge.mikutoga.pmd.Deg3d;
+import jp.sourceforge.mikutoga.pmd.DynamicsInfo;
+import jp.sourceforge.mikutoga.pmd.IKChain;
+import jp.sourceforge.mikutoga.pmd.JointInfo;
+import jp.sourceforge.mikutoga.pmd.Material;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.MorphType;
+import jp.sourceforge.mikutoga.pmd.MorphVertex;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos2d;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Rad3d;
+import jp.sourceforge.mikutoga.pmd.RigidGroup;
+import jp.sourceforge.mikutoga.pmd.RigidInfo;
+import jp.sourceforge.mikutoga.pmd.RigidShape;
+import jp.sourceforge.mikutoga.pmd.RigidShapeType;
+import jp.sourceforge.mikutoga.pmd.ShadeInfo;
+import jp.sourceforge.mikutoga.pmd.Surface;
+import jp.sourceforge.mikutoga.pmd.ToonMap;
+import jp.sourceforge.mikutoga.pmd.TripletRange;
+import jp.sourceforge.mikutoga.pmd.Vec3d;
+import jp.sourceforge.mikutoga.pmd.Vertex;
+import jp.sourceforge.mikutoga.xml.BasicXmlExporter;
+import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
+
+/**
+ * XML形式でPMDモデルデータを出力する。
+ */
+public class PmdXmlExporter extends BasicXmlExporter{
+
+    private static final String TOP_COMMENT =
+            "  MikuMikuDance\n    model-data(*.pmd) on XML";
+    private static final String SCHEMA_LOCATION =
+            PmdXmlResources.NS_PMDXML + " " + PmdXmlResources.SCHEMA_PMDXML;
+
+    /** 改行文字列 CR。 */
+    private static final String CR = "\r";       // 0x0d
+    /** 改行文字列 LF。 */
+    private static final String LF = "\n";       // 0x0a
+    /** 改行文字列 CRLF。 */
+    private static final String CRLF = CR + LF;  // 0x0d, 0x0a
+
+    private static final String PFX_SURFACEGROUP = "sg";
+    private static final String PFX_TOONFILE = "tf";
+    private static final String PFX_VERTEX = "vtx";
+    private static final String PFX_BONE = "bn";
+    private static final String PFX_RIGID = "rd";
+    private static final String PFX_RIGIDGROUP = "rg";
+
+    private static final String BONETYPE_COMMENT =
+          "Bone types:\n"
+        + "[0 : ROTATE      : Rotate       : 回転           :]\n"
+        + "[1 : ROTMOV      : Rotate/Move  : 回転/移動      :]\n"
+        + "[2 : IK          : IK           : IK             :]\n"
+        + "[3 : UNKNOWN     : Unknown      : 不明           :]\n"
+        + "[4 : UNDERIK     : Under IK     : IK影響下(回転) :]\n"
+        + "[5 : UNDERROT    : Under rotate : 回転影響下     :]\n"
+        + "[6 : IKCONNECTED : IK connected : IK接続先       :]\n"
+        + "[7 : HIDDEN      : Hidden       : 非表示         :]\n"
+        + "[8 : TWIST       : Twist        : 捩り           :]\n"
+        + "[9 : LINKEDROT   : Linked Rotate: 回転連動       :]\n";
+
+    private static final String MORPHTYPE_COMMENT =
+          "Morph types:\n"
+        + "[1 : EYEBROW : まゆ   ]\n"
+        + "[2 : EYE     : 目     ]\n"
+        + "[3 : LIP     : リップ ]\n"
+        + "[4 : EXTRA   : その他 ]\n";
+
+    private static final String RIGIDBEHAVIOR_COMMENT =
+          "Rigid behavior types:\n"
+        + "[0 : FOLLOWBONE    : ボーン追従       ]\n"
+        + "[1 : ONLYDYNAMICS  : 物理演算         ]\n"
+        + "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
+
+    private String generator = "";
+
+    /**
+     * コンストラクタ。
+     * 文字エンコーディングはUTF-8が用いられる。
+     * @param stream 出力ストリーム
+     */
+    public PmdXmlExporter(OutputStream stream){
+        super(stream);
+        return;
+    }
+
+    /**
+     * Generatorメタ情報を設定する。
+     * @param generatorArg Generatorメタ情報
+     * @throws NullPointerException 引数がnull
+     */
+    public void setGenerator(String generatorArg)
+            throws NullPointerException{
+        if(generatorArg == null) throw new NullPointerException();
+        this.generator = generatorArg;
+        return;
+    }
+
+    /**
+     * 任意の文字列がBasicLatin文字のみから構成されるか判定する。
+     * @param seq 文字列
+     * @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue
+     */
+    public static boolean hasOnlyBasicLatin(CharSequence seq){
+        if(seq == null) return true;
+        int length = seq.length();
+        for(int pos = 0; pos < length; pos++){
+            char ch = seq.charAt(pos);
+            if(ch > 0x007f) return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public PmdXmlExporter ind() throws IOException{
+        super.ind();
+        return this;
+    }
+
+    /**
+     * 文字参照によるエスケープを補佐するためのコメントを出力する。
+     * @param seq 文字列
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putUnescapedComment(CharSequence seq)
+            throws IOException{
+        if( ! isBasicLatinOnlyOut() ) return this;
+        if(hasOnlyBasicLatin(seq)) return this;
+        put(' ').putLineComment(seq);
+        return this;
+    }
+
+    /**
+     * 多言語化された各種識別名を出力する。
+     * プライマリ名は出力対象外。
+     * @param text 多言語文字列
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putI18nName(I18nText text) throws IOException{
+        for(String lang639 : text.lang639CodeList()){
+            if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;
+            String name = text.getText(lang639);
+            ind().put("<i18nName ");
+            putAttr("lang", lang639).put(' ');
+            putAttr("name", name);
+            put(" />");
+            putUnescapedComment(name);
+            ln();
+        }
+        return this;
+    }
+
+    /**
+     * 番号付けされたID(IDREF)属性を出力する。
+     * @param attrName 属性名
+     * @param prefix IDプレフィクス
+     * @param num 番号
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
+                                                 CharSequence prefix,
+                                                 int num )
+            throws IOException{
+        put(attrName).put("=\"");
+        put(prefix).put(num);
+        put('"');
+        return this;
+    }
+
+    /**
+     * 番号付けされたID(IDREF)属性を出力する。
+     * @param attrName 属性名
+     * @param prefix IDプレフィクス
+     * @param numbered 番号付けされたオブジェクト
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
+                                                 CharSequence prefix,
+                                                 SerialNumbered numbered )
+            throws IOException{
+        putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());
+        return this;
+    }
+
+    /**
+     * 位置情報を出力する。
+     * @param position 位置情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putPosition(Pos3d position) throws IOException{
+        put("<position ");
+        putFloatAttr("x", position.getXPos()).put(' ');
+        putFloatAttr("y", position.getYPos()).put(' ');
+        putFloatAttr("z", position.getZPos()).put(' ');
+        put("/>");
+        return this;
+    }
+
+    /**
+     * 姿勢情報(ラジアン)を出力する。
+     * @param rotation 姿勢情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putRadRotation(Rad3d rotation)
+            throws IOException{
+        put("<radRotation ");
+        putFloatAttr("xRad", rotation.getXRad()).put(' ');
+        putFloatAttr("yRad", rotation.getYRad()).put(' ');
+        putFloatAttr("zRad", rotation.getZRad()).put(' ');
+        put("/>");
+        return this;
+    }
+
+    /**
+     * 多言語識別名属性のローカルな名前をコメント出力する。
+     * @param name 多言語識別名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putLocalNameComment(I18nText name)
+            throws IOException{
+        String localName = name.getText();
+        ind().putLineComment(localName);
+        return this;
+    }
+
+    /**
+     * 多言語識別名属性のプライマリな名前を出力する。
+     * @param attrName 属性名
+     * @param name 多言語識別名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected PmdXmlExporter putPrimaryNameAttr(CharSequence attrName,
+                                                   I18nText name)
+            throws IOException{
+        String primaryName = name.getPrimaryText();
+        putAttr(attrName, primaryName);
+        return this;
+    }
+
+    /**
+     * PMDモデルデータをXML形式で出力する。
+     * @param model PMDモデルデータ
+     * @throws IOException 出力エラー
+     */
+    public void putPmdModel(PmdModel model) throws IOException{
+        ind().put("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").ln(2);
+
+        ind().putBlockComment(TOP_COMMENT).ln(2);
+
+        /*
+        ind().put("<!DOCTYPE pmdModel").ln();
+        ind().put(" SYSTEM \"")
+             .put(PmdXmlResources.DTD_PMDXML)
+             .put("\" >")
+             .ln(3);
+         */
+
+        I18nText modelName = model.getModelName();
+        ind().putLocalNameComment(modelName).ln();
+        ind().put("<pmdModel").ln();
+        pushNest();
+        ind().putAttr("xmlns", PmdXmlResources.NS_PMDXML).ln();
+        ind().putAttr("xmlns:xsi", XmlResourceResolver.NS_XSD).ln();
+        ind().putAttr("xsi:schemaLocation", SCHEMA_LOCATION).ln();
+        ind().putAttr("schemaVersion", PmdXmlResources.VER_PMDXML).ln(2);
+        ind().putPrimaryNameAttr("name", modelName).ln();
+        popNest();
+        put(">").ln(2);
+
+        putModelInfo(model).flush();
+        putMetaInfo(model).flush();
+        putMaterialList(model).flush();
+        putToonMap(model).flush();
+        putBoneList(model).flush();
+        putBoneGroupList(model).flush();
+        putIKChainList(model).flush();
+        putMorphList(model).flush();
+        putRigidList(model).flush();
+        putRigidGroupList(model).flush();
+        putJointList(model).flush();
+        putSurfaceGroupList(model).flush();
+        putVertexList(model).flush();
+
+        ind().put("</pmdModel>").ln(2);
+        ind().put("<!-- EOF -->").ln();
+
+        return;
+    }
+
+    /**
+     * モデル基本情報を出力する。
+     * @param model モデル情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putModelInfo(PmdModel model)
+            throws IOException{
+        I18nText modelName = model.getModelName();
+        putI18nName(modelName);
+        ln();
+
+        I18nText description = model.getDescription();
+        for(String lang639 : description.lang639CodeList()){
+            String descText = description.getText(lang639);
+            putDescription(lang639, descText);
+            ln();
+        }
+
+        return this;
+    }
+
+    /**
+     * モデル詳細テキストを出力する。
+     * @param lang639 言語コード
+     * @param content 詳細内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putDescription(CharSequence lang639,
+                                              CharSequence content)
+            throws IOException{
+        String text = content.toString();
+        text = text.replace(CRLF, LF);
+        text = text.replace(CR,   LF);
+
+        ind().put("<description");
+        if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){
+            put(" ");
+            putAttr("lang", lang639);
+        }
+        put(">").ln();
+
+        putBRedContent(text);
+
+        ln();
+        ind().put("</description>").ln();
+
+        if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
+            putBlockComment(text);
+        }
+
+        return this;
+    }
+
+    /**
+     * break要素を含む要素内容を出力する。
+     * 必要に応じてXML定義済み実体文字が割り振られた文字、
+     * コントロールコード、および非BasicLatin文字がエスケープされる。
+     * \nはbrタグに変換される。
+     * @param content 内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    protected BasicXmlExporter putBRedContent(CharSequence content)
+            throws IOException{
+        int length = content.length();
+
+        for(int pos = 0; pos < length; pos++){
+            char ch = content.charAt(pos);
+            if(ch == '\n'){
+                put("<br/>").ln();
+            }else if(Character.isISOControl(ch)){
+                putCharRef2Hex(ch);
+            }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){
+                putCharRef4Hex(ch);
+            }else{
+                switch(ch){
+                case '&':  put("&amp;");  break;
+                case '<':  put("&lt;");   break;
+                case '>':  put("&gt;");   break;
+                case '"':  put("&quot;"); break;
+                case '\'': put("&apos;"); break;
+                default:   put(ch);       break;
+                }
+            }
+        }
+
+        return this;
+    }
+
+    /**
+     * 各種メタ情報を出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putMetaInfo(PmdModel model) throws IOException{
+        ind().put("<license>").ln();
+        ind().put("</license>").ln(2);
+
+        ind().put("<credits>").ln();
+        ind().put("</credits>").ln(2);
+
+        ind().put("<meta ");
+        putAttr("name", "generator").put(' ')
+                                    .putAttr("content", this.generator);
+        put(" />").ln();
+        ind().put("<meta ");
+        putAttr("name", "siteURL").put(' ').putAttr("content", "");
+        put(" />").ln();
+        ind().put("<meta ");
+        putAttr("name", "imageURL").put(' ').putAttr("content", "");
+        put(" />").ln(2);
+
+        return this;
+    }
+
+    /**
+     * マテリアル素材一覧を出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putMaterialList(PmdModel model)
+            throws IOException{
+        ind().put("<materialList>").ln(2);
+        pushNest();
+
+        int ct = 0;
+        for(Material material : model.getMaterialList()){
+            putMaterial(material, ct++);
+        }
+
+        popNest();
+        ind().put("</materialList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * マテリアル素材情報を出力する。
+     * @param material マテリアル素材
+     * @param no マテリアル通し番号
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putMaterial(Material material, int no)
+            throws IOException{
+        String bool;
+        if(material.getEdgeAppearance()) bool = "true";
+        else                             bool = "false";
+        I18nText name = material.getMaterialName();
+        String primary = name.getPrimaryText();
+        String local = name.getText();
+
+        if(local != null && local.length() > 0){
+            ind().putLineComment(local).ln();
+        }
+        ind().put("<material ");
+        if(primary != null && primary.length() > 0){
+            putAttr("name", primary).put(' ');
+        }
+
+        putAttr("showEdge", bool);
+        put(" ");
+        putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);
+        put('>').ln();
+        pushNest();
+
+        putI18nName(name);
+
+        float[] rgba = new float[4];
+
+        Color diffuse = material.getDiffuseColor();
+        diffuse.getRGBComponents(rgba);
+        ind().put("<diffuse ");
+        putFloatAttr("r", rgba[0]).put(' ');
+        putFloatAttr("g", rgba[1]).put(' ');
+        putFloatAttr("b", rgba[2]).put(' ');
+        putFloatAttr("alpha", rgba[3]).put(' ');
+        put("/>").ln();
+
+        Color specular = material.getSpecularColor();
+        specular.getRGBComponents(rgba);
+        float shininess = material.getShininess();
+        ind().put("<specular ");
+        putFloatAttr("r", rgba[0]).put(' ');
+        putFloatAttr("g", rgba[1]).put(' ');
+        putFloatAttr("b", rgba[2]).put(' ');
+        putFloatAttr("shininess", shininess).put(' ');
+        put("/>").ln();
+
+        Color ambient = material.getAmbientColor();
+        ambient.getRGBComponents(rgba);
+        ind().put("<ambient ");
+        putFloatAttr("r", rgba[0]).put(' ');
+        putFloatAttr("g", rgba[1]).put(' ');
+        putFloatAttr("b", rgba[2]).put(' ');
+        put("/>").ln();
+
+        ShadeInfo shade = material.getShadeInfo();
+        String textureFileName = shade.getTextureFileName();
+        String spheremapFileName = shade.getSpheremapFileName();
+
+        if(shade.isValidToonIndex()){
+            ind().put("<toon ");
+            int toonIdx = shade.getToonIndex();
+            putNumberedIdAttr("toonFileIdRef", PFX_TOONFILE, toonIdx);
+            put(" />");
+            String toonFileName = shade.getToonFileName();
+            if(toonFileName != null && toonFileName.length() > 0){
+                put(' ').putLineComment(toonFileName);
+            }
+            ln();
+        }
+
+        if(textureFileName != null && textureFileName.length() > 0){
+            ind().put("<textureFile ");
+            putAttr("winFileName", textureFileName);
+            put(" />").ln();
+        }
+
+        if(spheremapFileName != null && spheremapFileName.length() > 0){
+            ind().put("<spheremapFile ");
+            putAttr("winFileName", spheremapFileName);
+            put(" />").ln();
+        }
+
+        popNest();
+        ind().put("</material>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * トゥーンファイルマッピング情報を出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putToonMap(PmdModel model)
+            throws IOException{
+        ind().put("<toonMap>").ln();
+        pushNest();
+
+        ToonMap map = model.getToonMap();
+        for(int index = 0; index <= 9; index++){
+            ind().putToon(map, index).ln();
+        }
+
+        popNest();
+        ind().put("</toonMap>").ln(2);
+        return this;
+    }
+
+    /**
+     * 個別のトゥーンファイル情報を出力する。
+     * @param map トゥーンマップ
+     * @param index インデックス値
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putToon(ToonMap map, int index)
+            throws IOException{
+        put("<toonDef ");
+        putNumberedIdAttr("toonFileId", PFX_TOONFILE, index).put(' ');
+        putIntAttr("index", index).put(' ');
+        String toonFile = map.getIndexedToon(index);
+        putAttr("winFileName", toonFile);
+        put(" />");
+        putUnescapedComment(toonFile);
+        return this;
+    }
+
+    /**
+     * サーフェイスグループリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putSurfaceGroupList(PmdModel model)
+            throws IOException{
+        ind().put("<surfaceGroupList>").ln(2);
+        pushNest();
+
+        int ct = 0;
+        for(Material material : model.getMaterialList()){
+            List<Surface> surfaceList = material.getSurfaceList();
+            putSurfaceList(surfaceList, ct++);
+        }
+
+        popNest();
+        ind().put("</surfaceGroupList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のサーフェイスグループを出力する。
+     * @param surfaceList サーフェイスのリスト
+     * @param index グループインデックス
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putSurfaceList(List<Surface> surfaceList,
+                                              int index)
+            throws IOException{
+        ind().put("<surfaceGroup ");
+        putNumberedIdAttr("surfaceGroupId", PFX_SURFACEGROUP, index);
+        put(">").ln();
+        pushNest();
+
+        for(Surface surface : surfaceList){
+            putSurface(surface);
+        }
+
+        popNest();
+        ind().put("</surfaceGroup>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のサーフェイスを出力する。
+     * @param surface サーフェイス
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putSurface(Surface surface)
+            throws IOException{
+        ind().put("<surface ");
+
+        Vertex vertex1 = surface.getVertex1();
+        Vertex vertex2 = surface.getVertex2();
+        Vertex vertex3 = surface.getVertex3();
+
+        putNumberedIdAttr("vtxIdRef1", PFX_VERTEX, vertex1).put(' ');
+        putNumberedIdAttr("vtxIdRef2", PFX_VERTEX, vertex2).put(' ');
+        putNumberedIdAttr("vtxIdRef3", PFX_VERTEX, vertex3).put(' ');
+
+        put("/>").ln();
+        return this;
+    }
+
+    /**
+     * 頂点リストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putVertexList(PmdModel model)
+            throws IOException{
+        ind().put("<vertexList>").ln(2);
+        pushNest();
+
+        for(Vertex vertex : model.getVertexList()){
+            putVertex(vertex);
+        }
+
+        popNest();
+        ind().put("</vertexList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別の頂点情報を出力する。
+     * @param vertex 頂点
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putVertex(Vertex vertex)
+            throws IOException{
+        String bool;
+        if(vertex.getEdgeAppearance()) bool = "true";
+        else                           bool = "false";
+
+        ind().put("<vertex ");
+        putNumberedIdAttr("vtxId", PFX_VERTEX, vertex).put(' ');
+        putAttr("showEdge", bool);
+        put(">").ln();
+        pushNest();
+
+        Pos3d position = vertex.getPosition();
+        ind().putPosition(position).ln();
+
+        Vec3d normal = vertex.getNormal();
+        ind().put("<normal ");
+        putFloatAttr("x", normal.getXVal()).put(' ');
+        putFloatAttr("y", normal.getYVal()).put(' ');
+        putFloatAttr("z", normal.getZVal()).put(' ');
+        put("/>").ln();
+
+        Pos2d uvPos = vertex.getUVPosition();
+        ind().put("<uvMap ");
+        putFloatAttr("u", uvPos.getXPos()).put(' ');
+        putFloatAttr("v", uvPos.getYPos()).put(' ');
+        put("/>").ln();
+
+        BoneInfo boneA = vertex.getBoneA();
+        BoneInfo boneB = vertex.getBoneB();
+        int weight = vertex.getWeightA();
+        ind().put("<skinning ");
+        putNumberedIdAttr("boneIdRef1", PFX_BONE, boneA).put(' ');
+        putNumberedIdAttr("boneIdRef2", PFX_BONE, boneB).put(' ');
+        putIntAttr("weightBalance", weight).put(' ');
+        put("/>").ln();
+
+        popNest();
+        ind().put("</vertex>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * ボーンリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putBoneList(PmdModel model)
+            throws IOException{
+        ind().put("<boneList>").ln(2);
+        pushNest();
+
+        putBlockComment(BONETYPE_COMMENT).ln();
+
+        for(BoneInfo bone : model.getBoneList()){
+            putBone(bone);
+        }
+
+        popNest();
+        ind().put("</boneList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のボーン情報を出力する。
+     * @param bone ボーン情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putBone(BoneInfo bone)
+            throws IOException{
+        I18nText i18nName = bone.getBoneName();
+        BoneType type = bone.getBoneType();
+
+        putLocalNameComment(i18nName).putLineComment(type.getGuiName()).ln();
+        ind().put("<bone ");
+        putPrimaryNameAttr("name", i18nName).put(' ');
+        putNumberedIdAttr("boneId", PFX_BONE, bone).put(' ');
+        putAttr("type", type.name());
+        put(">").ln();
+        pushNest();
+
+        putI18nName(i18nName);
+
+        Pos3d position = bone.getPosition();
+        ind().putPosition(position).ln();
+
+        BoneInfo ikBone = bone.getIKBone();
+        if(bone.getBoneType() == BoneType.LINKEDROT){
+            ind().put("<rotationRatio ");
+            putIntAttr("ratio", bone.getRotationRatio());
+            put(" />").ln();
+        }else if(ikBone != null){
+            ind().put("<ikBone ");
+            putNumberedIdAttr("boneIdRef", PFX_BONE, ikBone);
+            put(" /> ");
+            String ikBoneName = "Ref:" + ikBone.getBoneName().getText();
+            putLineComment(ikBoneName);
+            ln();
+        }
+
+        StringBuilder chainComment = new StringBuilder();
+        ind().put("<boneChain");
+        BoneInfo prev = bone.getPrevBone();
+        BoneInfo next = bone.getNextBone();
+        if(prev != null){
+            put(' ');
+            putNumberedIdAttr("prevBoneIdRef", PFX_BONE, prev);
+            chainComment.append('[')
+                        .append(prev.getBoneName().getPrimaryText())
+                        .append(']')
+                        .append("=> #");
+        }
+        if(next != null){
+            put(' ');
+            putNumberedIdAttr("nextBoneIdRef", PFX_BONE, next);
+            if(chainComment.length() <= 0) chainComment.append("#");
+            chainComment.append(" =>")
+                        .append('[')
+                        .append(next.getBoneName().getPrimaryText())
+                        .append(']');
+        }
+        put(" />").ln();
+        ind().putLineComment(chainComment).ln();
+
+        popNest();
+        ind().put("</bone>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * ボーングループリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putBoneGroupList(PmdModel model)
+            throws IOException{
+        ind().put("<boneGroupList>").ln(2);
+        pushNest();
+
+        for(BoneGroup group : model.getBoneGroupList()){
+            if(group.isDefaultBoneGroup()) continue;
+            putBoneGroup(group);
+        }
+
+        popNest();
+        ind().put("</boneGroupList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のボーングループ情報を出力する。
+     * @param group ボーングループ情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putBoneGroup(BoneGroup group)
+            throws IOException{
+        I18nText i18nName = group.getGroupName();
+
+        putLocalNameComment(i18nName).ln();
+        ind().put("<boneGroup ");
+        putPrimaryNameAttr("name", i18nName);
+        put(">").ln();
+        pushNest();
+
+        putI18nName(i18nName);
+
+        for(BoneInfo bone : group){
+            ind().put("<boneGroupMember ");
+            putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
+            put(" /> ");
+            String boneName = "Ref:" + bone.getBoneName().getText();
+            putLineComment(boneName).ln();
+        }
+
+        popNest();
+        ind().put("</boneGroup>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * IKチェーンリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putIKChainList(PmdModel model)
+            throws IOException{
+        ind().put("<ikChainList>").ln(2);
+        pushNest();
+
+        for(IKChain chain : model.getIKChainList()){
+            putIKChain(chain);
+        }
+
+        popNest();
+        ind().put("</ikChainList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のIKチェーン情報を出力する。
+     * @param chain チェーン情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putIKChain(IKChain chain)
+            throws IOException{
+        int depth = chain.getIKDepth();
+        float weight = chain.getIKWeight();
+        BoneInfo ikBone = chain.getIkBone();
+
+        ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();
+        ind().put("<ikChain ");
+        putNumberedIdAttr("ikBoneIdRef", PFX_BONE, ikBone).put(' ');
+        putIntAttr("recursiveDepth", depth).put(' ');
+        putFloatAttr("weight", weight);
+        put("> ").ln();
+        pushNest();
+
+        for(BoneInfo bone : chain){
+            ind().put("<chainOrder ");
+            putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
+            put(" /> ");
+            putLineComment("Ref:" + bone.getBoneName().getText());
+            ln();
+        }
+
+        popNest();
+        ind().put("</ikChain>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * モーフリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putMorphList(PmdModel model)
+            throws IOException{
+        ind().put("<morphList>").ln(2);
+        pushNest();
+
+        putBlockComment(MORPHTYPE_COMMENT).ln();
+
+        Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
+        for(MorphType type : MorphType.values()){
+            if(type == MorphType.BASE) continue;
+            List<MorphPart> partList = morphMap.get(type);
+            if(partList == null) continue;
+            for(MorphPart part : partList){
+                putMorphPart(part);
+            }
+        }
+
+        popNest();
+        ind().put("</morphList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のモーフ情報を出力する。
+     * @param part モーフ情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putMorphPart(MorphPart part)
+            throws IOException{
+        I18nText i18nName = part.getMorphName();
+        String primary = i18nName.getPrimaryText();
+
+        ind().put("<morph ");
+        putAttr("name", primary).put(' ');
+        putAttr("type", part.getMorphType().name());
+        put(">");
+        putUnescapedComment(primary);
+        ln();
+        pushNest();
+
+        putI18nName(i18nName);
+
+        for(MorphVertex mvertex : part){
+            Pos3d offset = mvertex.getOffset();
+            Vertex base = mvertex.getBaseVertex();
+
+            ind().put("<morphVertex ");
+            putNumberedIdAttr("vtxIdRef", PFX_VERTEX, base).put(' ');
+            putFloatAttr("xOff", offset.getXPos()).put(' ');
+            putFloatAttr("yOff", offset.getYPos()).put(' ');
+            putFloatAttr("zOff", offset.getZPos()).put(' ');
+            put("/>");
+            ln();
+        }
+
+        popNest();
+        ind().put("</morph>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 剛体リストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putRigidList(PmdModel model)
+            throws IOException{
+        ind().put("<rigidList>").ln(2);
+        pushNest();
+
+        putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
+
+        for(RigidInfo rigid : model.getRigidList()){
+            putRigid(rigid);
+        }
+
+        popNest();
+        ind().put("</rigidList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別の剛体情報を出力する。
+     * @param rigid 剛体情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putRigid(RigidInfo rigid)
+            throws IOException{
+        BoneInfo linkedBone = rigid.getLinkedBone();
+        I18nText i18nName = rigid.getRigidName();
+        String primary = i18nName.getPrimaryText();
+
+        putLocalNameComment(i18nName).ln();
+        ind().put("<rigid ");
+        putAttr("name", primary).put(' ');
+        putNumberedIdAttr("rigidId", PFX_RIGID, rigid).put(' ');
+        putAttr("behavior", rigid.getBehaviorType().name());
+        put(">").ln();
+        pushNest();
+
+        putI18nName(i18nName);
+
+        if(linkedBone != null){
+            ind().put("<linkedBone ");
+            putNumberedIdAttr("boneIdRef", PFX_BONE, linkedBone);
+            put(" /> ");
+            putLineComment("Ref:" + linkedBone.getBoneName().getText());
+            ln(2);
+        }
+
+        RigidShape shape = rigid.getRigidShape();
+        putRigidShape(shape);
+
+        Pos3d position = rigid.getPosition();
+        ind().putPosition(position).ln();
+
+        Rad3d rotation = rigid.getRotation();
+        ind().putRadRotation(rotation).ln();
+
+        DynamicsInfo dynamics = rigid.getDynamicsInfo();
+        putDynamics(dynamics).ln();
+
+        for(RigidGroup group : rigid.getThroughGroupColl()){
+            ind().put("<throughRigidGroup ");
+            putNumberedIdAttr("rigidGroupIdRef",
+                              PFX_RIGIDGROUP,
+                              group.getSerialNumber() + 1).put(' ');
+            put(" />").ln();
+        }
+
+        popNest();
+        ind().put("</rigid>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 剛体形状を出力する。
+     * @param shape 剛体形状
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putRigidShape(RigidShape shape)
+            throws IOException{
+        RigidShapeType type = shape.getShapeType();
+
+        switch(type){
+        case BOX:
+            ind().put("<rigidShapeBox ");
+            putFloatAttr("width", shape.getWidth()).put(' ');
+            putFloatAttr("height", shape.getHeight()).put(' ');
+            putFloatAttr("depth", shape.getDepth()).put(' ');
+            break;
+        case SPHERE:
+            ind().put("<rigidShapeSphere ");
+            putFloatAttr("radius", shape.getRadius()).put(' ');
+            break;
+        case CAPSULE:
+            ind().put("<rigidShapeCapsule ");
+            putFloatAttr("height", shape.getHeight()).put(' ');
+            putFloatAttr("radius", shape.getRadius()).put(' ');
+            break;
+        default:
+            assert false;
+            throw new AssertionError();
+        }
+
+        put("/>").ln();
+
+        return this;
+    }
+
+    /**
+     * 力学設定を出力する。
+     * @param dynamics 力学設定
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putDynamics(DynamicsInfo dynamics)
+            throws IOException{
+        ind().put("<dynamics").ln();
+        pushNest();
+        ind().putFloatAttr("mass", dynamics.getMass()).ln();
+        ind().putFloatAttr("dampingPosition",
+                dynamics.getDampingPosition()).ln();
+        ind().putFloatAttr("dampingRotation",
+                dynamics.getDampingRotation()).ln();
+        ind().putFloatAttr("restitution", dynamics.getRestitution()).ln();
+        ind().putFloatAttr("friction", dynamics.getFriction()).ln();
+        popNest();
+        ind().put("/>").ln();
+
+        return this;
+    }
+
+    /**
+     * 剛体グループリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putRigidGroupList(PmdModel model)
+            throws IOException{
+        ind().put("<rigidGroupList>").ln(2);
+        pushNest();
+
+        for(RigidGroup group : model.getRigidGroupList()){
+            ind().put("<rigidGroup ");
+            putNumberedIdAttr("rigidGroupId",
+                              PFX_RIGIDGROUP,
+                              group.getSerialNumber() + 1);
+            List<RigidInfo> rigidList = group.getRigidList();
+            if(rigidList.size() <= 0){
+                put(" />").ln(2);
+                continue;
+            }
+            put(">").ln();
+            pushNest();
+
+            for(RigidInfo rigid : rigidList){
+                ind().put("<rigidGroupMember ");
+                putNumberedIdAttr("rigidIdRef", PFX_RIGID, rigid).put(' ');
+                put("/>");
+                put(' ');
+                putLineComment("Ref:" + rigid.getRigidName().getText());
+                ln();
+            }
+
+            popNest();
+            ind().put("</rigidGroup>").ln(2);
+        }
+
+        popNest();
+        ind().put("</rigidGroupList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * ジョイントリストを出力する。
+     * @param model モデルデータ
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putJointList(PmdModel model)
+            throws IOException{
+        ind().put("<jointList>").ln(2);
+        pushNest();
+
+        for(JointInfo joint : model.getJointList()){
+            putJoint(joint);
+        }
+
+        popNest();
+        ind().put("</jointList>").ln(2);
+
+        return this;
+    }
+
+    /**
+     * 個別のジョイント情報を出力する。
+     * @param joint ジョイント情報
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    private PmdXmlExporter putJoint(JointInfo joint)
+            throws IOException{
+        I18nText i18nName = joint.getJointName();
+
+        putLocalNameComment(i18nName).ln();
+        ind().put("<joint ");
+        putPrimaryNameAttr("name", i18nName);
+        put(">").ln();
+        pushNest();
+
+        putI18nName(i18nName);
+
+        RigidInfo rigidA = joint.getRigidA();
+        RigidInfo rigidB = joint.getRigidB();
+        ind().put("<jointedRigidPair ");
+        putNumberedIdAttr("rigidIdRef1", PFX_RIGID, rigidA).put(' ');
+        putNumberedIdAttr("rigidIdRef2", PFX_RIGID, rigidB).put(' ');
+        put("/>").ln();
+        ind();
+        putLineComment("[" + rigidA.getRigidName().getText() + "]"
+                + " <=> [" + rigidB.getRigidName().getText() + "]");
+        ln(2);
+
+        Pos3d position = joint.getPosition();
+        ind().putPosition(position).ln();
+
+        TripletRange posRange = joint.getPositionRange();
+        ind().put("<limitPosition").ln();
+        pushNest();
+        ind();
+        putFloatAttr("xFrom", posRange.getXFrom()).put(' ');
+        putFloatAttr("xTo",   posRange.getXTo()).ln();
+        ind();
+        putFloatAttr("yFrom", posRange.getYFrom()).put(' ');
+        putFloatAttr("yTo",   posRange.getYTo()).ln();
+        ind();
+        putFloatAttr("zFrom", posRange.getZFrom()).put(' ');
+        putFloatAttr("zTo",   posRange.getZTo()).ln();
+        popNest();
+        ind().put("/>").ln(2);
+
+        Rad3d rotation = joint.getRotation();
+        ind().putRadRotation(rotation).ln();
+        TripletRange rotRange = joint.getRotationRange();
+        ind().put("<limitRotation").ln();
+        pushNest();
+        ind();
+        putFloatAttr("xFrom", rotRange.getXFrom()).put(' ');
+        putFloatAttr("xTo",   rotRange.getXTo()).ln();
+        ind();
+        putFloatAttr("yFrom", rotRange.getYFrom()).put(' ');
+        putFloatAttr("yTo",   rotRange.getYTo()).ln();
+        ind();
+        putFloatAttr("zFrom", rotRange.getZFrom()).put(' ');
+        putFloatAttr("zTo",   rotRange.getZTo()).ln();
+        popNest();
+        ind().put("/>").ln(2);
+
+        Pos3d elaPosition = joint.getElasticPosition();
+        ind().put("<elasticPosition ");
+        putFloatAttr("x", elaPosition.getXPos()).put(' ');
+        putFloatAttr("y", elaPosition.getYPos()).put(' ');
+        putFloatAttr("z", elaPosition.getZPos()).put(' ');
+        put("/>").ln();
+
+        Deg3d elaRotation = joint.getElasticRotation();
+        ind().put("<elasticRotation ");
+        putFloatAttr("xDeg", elaRotation.getXDeg()).put(' ');
+        putFloatAttr("yDeg", elaRotation.getYDeg()).put(' ');
+        putFloatAttr("zDeg", elaRotation.getZDeg()).put(' ');
+        put("/>").ln(2);
+
+        popNest();
+        ind().put("</joint>").ln(2);
+
+        return this;
+    }
+
+}
index d9a367d..2ed7955 100644 (file)
-/*\r
- * xml resources for PMD-XML\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.xml;\r
-\r
-import java.net.URI;\r
-import java.net.URISyntaxException;\r
-import javax.xml.XMLConstants;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.validation.Schema;\r
-import javax.xml.validation.SchemaFactory;\r
-import jp.sourceforge.mikutoga.xml.XmlResourceResolver;\r
-import org.xml.sax.ErrorHandler;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * XML各種リソースの定義。\r
- */\r
-public final class PmdXmlResources {\r
-\r
-    public static final String NS_PMDXML =\r
-            "http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009";\r
-    public static final String SCHEMA_PMDXML =\r
-            "http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd";\r
-    public static final String DTD_PMDXML =\r
-            "http://mikutoga.sourceforge.jp/xml/dtd/pmdxml-101009.dtd";\r
-    public static final String VER_PMDXML =\r
-            "101009";\r
-    public static final String LOCAL_SCHEMA_PMDXML =\r
-            "resources/pmdxml-101009.xsd";\r
-    public static final String LOCAL_DTD_PMDXML =\r
-            "resources/pmdxml-101009.dtd";\r
-\r
-    public static final URI URI_SCHEMA_PMDXML = URI.create(SCHEMA_PMDXML);\r
-    public static final URI URI_DTD_PMDXML = URI.create(DTD_PMDXML);\r
-    public static final URI RES_SCHEMA_PMDXML;\r
-    public static final URI RES_DTD_PMDXML;\r
-\r
-    private static final Class THISCLASS = PmdXmlResources.class;\r
-\r
-    static{\r
-        Object dummy = new PmdXmlResources();\r
-\r
-        try{\r
-            RES_SCHEMA_PMDXML =\r
-                    THISCLASS.getResource(LOCAL_SCHEMA_PMDXML).toURI();\r
-            RES_DTD_PMDXML =\r
-                    THISCLASS.getResource(LOCAL_DTD_PMDXML).toURI();\r
-        }catch(URISyntaxException e){\r
-            throw new ExceptionInInitializerError(e);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * 隠しコンストラクタ。\r
-     */\r
-    private PmdXmlResources(){\r
-        super();\r
-        assert this.getClass().equals(THISCLASS);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ビルダの生成。\r
-     * @param handler エラーハンドラ\r
-     * @return ビルダ\r
-     * @throws SAXException パースエラー\r
-     * @throws ParserConfigurationException 構成エラー\r
-     */\r
-    public static DocumentBuilder newBuilder(ErrorHandler handler)\r
-            throws SAXException, ParserConfigurationException {\r
-        XmlResourceResolver resolver = new XmlResourceResolver();\r
-        resolver.putURIMap(URI_SCHEMA_PMDXML, RES_SCHEMA_PMDXML);\r
-        resolver.putURIMap(URI_DTD_PMDXML, RES_DTD_PMDXML);\r
-\r
-        SchemaFactory schemaFactory =\r
-                SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);\r
-        schemaFactory.setResourceResolver(resolver);\r
-        schemaFactory.setErrorHandler(handler);\r
-        Schema schema = schemaFactory.newSchema();\r
-\r
-        DocumentBuilderFactory builderFactory =\r
-                DocumentBuilderFactory.newInstance();\r
-        builderFactory.setCoalescing(true);\r
-        builderFactory.setExpandEntityReferences(true);\r
-        builderFactory.setIgnoringComments(true);\r
-        builderFactory.setIgnoringElementContentWhitespace(false);\r
-        builderFactory.setNamespaceAware(true);\r
-        builderFactory.setValidating(false);\r
-        builderFactory.setSchema(schema);\r
-\r
-        DocumentBuilder builder = builderFactory.newDocumentBuilder();\r
-        builder.setEntityResolver(resolver);\r
-        builder.setErrorHandler(handler);\r
-\r
-        return builder;\r
-    }\r
-\r
-}\r
+/*
+ * xml resources for PMD-XML
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.xml;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * XML各種リソースの定義。
+ */
+public final class PmdXmlResources {
+
+    public static final String NS_PMDXML =
+            "http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009";
+    public static final String SCHEMA_PMDXML =
+            "http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd";
+    public static final String DTD_PMDXML =
+            "http://mikutoga.sourceforge.jp/xml/dtd/pmdxml-101009.dtd";
+    public static final String VER_PMDXML =
+            "101009";
+    public static final String LOCAL_SCHEMA_PMDXML =
+            "resources/pmdxml-101009.xsd";
+    public static final String LOCAL_DTD_PMDXML =
+            "resources/pmdxml-101009.dtd";
+
+    public static final URI URI_SCHEMA_PMDXML = URI.create(SCHEMA_PMDXML);
+    public static final URI URI_DTD_PMDXML = URI.create(DTD_PMDXML);
+    public static final URI RES_SCHEMA_PMDXML;
+    public static final URI RES_DTD_PMDXML;
+
+    private static final Class THISCLASS = PmdXmlResources.class;
+
+    static{
+        Object dummy = new PmdXmlResources();
+
+        try{
+            RES_SCHEMA_PMDXML =
+                    THISCLASS.getResource(LOCAL_SCHEMA_PMDXML).toURI();
+            RES_DTD_PMDXML =
+                    THISCLASS.getResource(LOCAL_DTD_PMDXML).toURI();
+        }catch(URISyntaxException e){
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private PmdXmlResources(){
+        super();
+        assert this.getClass().equals(THISCLASS);
+        return;
+    }
+
+    /**
+     * ビルダの生成。
+     * @param handler エラーハンドラ
+     * @return ビルダ
+     * @throws SAXException パースエラー
+     * @throws ParserConfigurationException 構成エラー
+     */
+    public static DocumentBuilder newBuilder(ErrorHandler handler)
+            throws SAXException, ParserConfigurationException {
+        XmlResourceResolver resolver = new XmlResourceResolver();
+        resolver.putURIMap(URI_SCHEMA_PMDXML, RES_SCHEMA_PMDXML);
+        resolver.putURIMap(URI_DTD_PMDXML, RES_DTD_PMDXML);
+
+        SchemaFactory schemaFactory =
+                SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        schemaFactory.setResourceResolver(resolver);
+        schemaFactory.setErrorHandler(handler);
+        Schema schema = schemaFactory.newSchema();
+
+        DocumentBuilderFactory builderFactory =
+                DocumentBuilderFactory.newInstance();
+        builderFactory.setCoalescing(true);
+        builderFactory.setExpandEntityReferences(true);
+        builderFactory.setIgnoringComments(true);
+        builderFactory.setIgnoringElementContentWhitespace(false);
+        builderFactory.setNamespaceAware(true);
+        builderFactory.setValidating(false);
+        builderFactory.setSchema(schema);
+
+        DocumentBuilder builder = builderFactory.newDocumentBuilder();
+        builder.setEntityResolver(resolver);
+        builder.setErrorHandler(handler);
+
+        return builder;
+    }
+
+}
index 84d15c0..b72a43c 100644 (file)
-/*\r
- * xml loader\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.xml;\r
-\r
-import java.awt.Color;\r
-import java.io.IOException;\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import jp.sourceforge.mikutoga.corelib.I18nText;\r
-import jp.sourceforge.mikutoga.corelib.ListUtil;\r
-import jp.sourceforge.mikutoga.pmd.BoneGroup;\r
-import jp.sourceforge.mikutoga.pmd.BoneInfo;\r
-import jp.sourceforge.mikutoga.pmd.BoneType;\r
-import jp.sourceforge.mikutoga.pmd.Deg3d;\r
-import jp.sourceforge.mikutoga.pmd.DynamicsInfo;\r
-import jp.sourceforge.mikutoga.pmd.IKChain;\r
-import jp.sourceforge.mikutoga.pmd.JointInfo;\r
-import jp.sourceforge.mikutoga.pmd.Material;\r
-import jp.sourceforge.mikutoga.pmd.MorphPart;\r
-import jp.sourceforge.mikutoga.pmd.MorphType;\r
-import jp.sourceforge.mikutoga.pmd.MorphVertex;\r
-import jp.sourceforge.mikutoga.pmd.PmdModel;\r
-import jp.sourceforge.mikutoga.pmd.Pos2d;\r
-import jp.sourceforge.mikutoga.pmd.Pos3d;\r
-import jp.sourceforge.mikutoga.pmd.Rad3d;\r
-import jp.sourceforge.mikutoga.pmd.RigidBehaviorType;\r
-import jp.sourceforge.mikutoga.pmd.RigidGroup;\r
-import jp.sourceforge.mikutoga.pmd.RigidInfo;\r
-import jp.sourceforge.mikutoga.pmd.RigidShape;\r
-import jp.sourceforge.mikutoga.pmd.RigidShapeType;\r
-import jp.sourceforge.mikutoga.pmd.ShadeInfo;\r
-import jp.sourceforge.mikutoga.pmd.Surface;\r
-import jp.sourceforge.mikutoga.pmd.ToonMap;\r
-import jp.sourceforge.mikutoga.pmd.TripletRange;\r
-import jp.sourceforge.mikutoga.pmd.Vec3d;\r
-import jp.sourceforge.mikutoga.pmd.Vertex;\r
-import jp.sourceforge.mikutoga.xml.DomUtils;\r
-import jp.sourceforge.mikutoga.xml.TogaXmlException;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.Node;\r
-import org.w3c.dom.NodeList;\r
-import org.xml.sax.InputSource;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * XML形式でのモデルファイルを読み込む。\r
- */\r
-public class Xml2PmdLoader {\r
-\r
-    private final DocumentBuilder builder;\r
-\r
-    private PmdModel model;\r
-\r
-    private final Map<String, Integer> toonIdxMap =\r
-            new HashMap<String, Integer>();\r
-    private final Map<String, BoneInfo> boneMap =\r
-            new HashMap<String, BoneInfo>();\r
-    private final Map<String, Vertex> vertexMap =\r
-            new HashMap<String, Vertex>();\r
-    private final Map<String, List<Surface>> surfaceGroupMap =\r
-            new HashMap<String, List<Surface>>();\r
-    private final Map<String, RigidInfo> rigidMap =\r
-            new HashMap<String, RigidInfo>();\r
-    private final Map<String, RigidGroup> rigidGroupMap =\r
-            new HashMap<String, RigidGroup>();\r
-\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param builder ビルダ\r
-     */\r
-    public Xml2PmdLoader(DocumentBuilder builder){\r
-        super();\r
-        this.builder = builder;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:string型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return 文字列\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    private static String getStringAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getStringAttr(elem, attrName);\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:boolean型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return 真ならtrue\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    private static boolean getBooleanAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getBooleanAttr(elem, attrName);\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:integer型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return int値\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    private static int getIntegerAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getIntegerAttr(elem, attrName);\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:float型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return float値\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    private static float getFloatAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getFloatAttr(elem, attrName);\r
-    }\r
-\r
-    /**\r
-     * 要素から日本語Windows用ファイル名を属性値として読み取る。\r
-     * 念のため文字U+00A5は文字U-005Cに変換される。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return ファイル名\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    private static String getSjisFileNameAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getSjisFileNameAttr(elem, attrName);\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素を1つだけ返す。\r
-     * @param parent 親要素\r
-     * @param tagName 子要素名\r
-     * @return 子要素\r
-     * @throws TogaXmlException 1つも見つからなかった\r
-     */\r
-    private static Element getChild(Element parent, String tagName)\r
-            throws TogaXmlException{\r
-        return DomUtils.getChild(parent, tagName);\r
-    }\r
-\r
-    /**\r
-     * 親要素が指定された名前の子要素を持つか判定する。\r
-     * @param parent 親要素\r
-     * @param tagName 子要素名\r
-     * @return 指定名の子要素が存在すればtrue\r
-     */\r
-    private static boolean hasChild(Element parent, String tagName){\r
-        return DomUtils.hasChild(parent, tagName);\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素のforeachを返す。\r
-     * @param parent 親要素\r
-     * @param childTag 子要素名\r
-     * @return 子要素のforeach\r
-     */\r
-    private static Iterable<Element> eachChild(Element parent,\r
-                                                    String childTag){\r
-        return DomUtils.getEachChild(parent, childTag);\r
-    }\r
-\r
-    /**\r
-     * グローバル名を取得する。\r
-     * 元要素のname属性及びi18nNameタグを持つ子要素が検索対象\r
-     * @param parent 元要素\r
-     * @return グローバル名。なければnull\r
-     */\r
-    private static String getGlobalName(Element parent){\r
-        NodeList nodeList = parent.getElementsByTagName("i18nName");\r
-        int length = nodeList.getLength();\r
-        for(int idx = 0; idx < length; idx++){\r
-            Node i18nNameNode = nodeList.item(idx);\r
-            Element i18nNameElem = (Element)i18nNameNode;\r
-            String lang = i18nNameElem.getAttribute("lang");\r
-            if(lang == null || lang.length() <= 0) continue;\r
-            if(lang.equals("en")){\r
-                String name = i18nNameElem.getAttribute("name");\r
-                return name;\r
-            }\r
-        }\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * brタグで区切られた文字列内容(Mixed content)を改行付き文字列に変換する。\r
-     * brタグはその出現回数だけ\nに変換される。\r
-     * 生文字列コンテンツ中の\n,\rは削除される。\r
-     * 改行文字以外のホワイトスペースは保持される。\r
-     * @param parent br要素及び文字列コンテンツを含む要素\r
-     * @return 変換された文字列\r
-     */\r
-    private static String getBRedContent(Element parent){\r
-        StringBuilder result = new StringBuilder();\r
-\r
-        for(Node node = parent.getFirstChild();\r
-            node != null;\r
-            node = node.getNextSibling() ){\r
-\r
-            switch(node.getNodeType()){\r
-            case Node.ELEMENT_NODE:\r
-                Element elem = (Element) node;\r
-                if("br".equals(elem.getTagName())){\r
-                    result.append('\n');\r
-                }\r
-                break;\r
-            case Node.TEXT_NODE:\r
-            case Node.CDATA_SECTION_NODE:\r
-                String content = node.getTextContent();\r
-                content = content.replace("\r", "");\r
-                content = content.replace("\n", "");\r
-                result.append(content);\r
-                break;\r
-            default:\r
-                break;\r
-            }\r
-        }\r
-\r
-        return result.toString();\r
-    }\r
-\r
-    /**\r
-     * 多言語名を取得する。\r
-     * @param baseElement 元要素\r
-     * @param text 多言語名\r
-     * @throws TogaXmlException あるべき属性が存在しない。\r
-     */\r
-    private static void buildI18nName(Element baseElement, I18nText text)\r
-            throws TogaXmlException{\r
-        String primaryText;\r
-        primaryText = getStringAttr(baseElement, "name");\r
-        text.setPrimaryText(primaryText);\r
-\r
-        for(Element i18nNameElem : eachChild(baseElement, "i18nName")){\r
-            String lang = getStringAttr(i18nNameElem, "lang");\r
-            String name = getStringAttr(i18nNameElem, "name");\r
-            if("en".equals(lang)){\r
-                text.setGlobalText(name);\r
-            }else{\r
-                text.setText(lang, text);\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * XMLのパースを開始する。\r
-     * @param source XML入力\r
-     * @return モデルデータ\r
-     * @throws SAXException 構文エラー\r
-     * @throws IOException 入力エラー\r
-     * @throws TogaXmlException 構文エラー\r
-     */\r
-    public PmdModel parse(InputSource source)\r
-            throws SAXException, IOException, TogaXmlException{\r
-        Document document = this.builder.parse(source);\r
-\r
-        this.model = new PmdModel();\r
-\r
-        Element pmdModelElem = document.getDocumentElement();\r
-\r
-        buildBasicInfo(pmdModelElem);\r
-\r
-        buildBoneList(pmdModelElem);\r
-        buildVertexList(pmdModelElem);\r
-        buildSurfaceList(pmdModelElem);\r
-\r
-        buildToonMap(pmdModelElem);\r
-        buildMaterialList(pmdModelElem);\r
-        buildIkChainList(pmdModelElem);\r
-        buildMorphList(pmdModelElem);\r
-        buildBoneGroupList(pmdModelElem);\r
-\r
-        buildRigidList(pmdModelElem);\r
-        buildRigidGroupList(pmdModelElem);\r
-        resolveThroughRigidGroup(pmdModelElem);\r
-\r
-        buildJointList(pmdModelElem);\r
-\r
-        return this.model;\r
-    }\r
-\r
-    private void buildBasicInfo(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        String primaryName = getStringAttr(pmdModelElem, "name");\r
-        String globalName = getGlobalName(pmdModelElem);\r
-\r
-        I18nText modelName = this.model.getModelName();\r
-        modelName.setPrimaryText(primaryName);\r
-        modelName.setGlobalText(globalName);\r
-\r
-        String primaryDescription = null;\r
-        String globalDescription = null;\r
-        for(Element descriptionElem :\r
-            eachChild(pmdModelElem, "description")){\r
-            String descriptionText = getBRedContent(descriptionElem);\r
-            if( ! descriptionElem.hasAttribute("lang") ){\r
-                primaryDescription = descriptionText;\r
-            }else{\r
-                String lang = getStringAttr(descriptionElem, "lang");\r
-                if(lang.equals("ja")){\r
-                    primaryDescription = descriptionText;\r
-                }else if(lang.equals("en")){\r
-                    globalDescription = descriptionText;\r
-                }\r
-            }\r
-        }\r
-\r
-        I18nText description = this.model.getDescription();\r
-        description.setPrimaryText(primaryDescription);\r
-        description.setGlobalText(globalDescription);\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildToonMap(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        ToonMap toonMap = this.model.getToonMap();\r
-\r
-        Element toonMapElem = getChild(pmdModelElem, "toonMap");\r
-\r
-        for(Element toonDefElem : eachChild(toonMapElem, "toonDef")){\r
-            String toonFileId = getStringAttr(toonDefElem, "toonFileId");\r
-            int toonIndex = getIntegerAttr(toonDefElem, "index");\r
-            String toonFile = getSjisFileNameAttr(toonDefElem, "winFileName");\r
-\r
-            toonMap.setIndexedToon(toonIndex, toonFile);\r
-            this.toonIdxMap.put(toonFileId, toonIndex);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildBoneList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element boneListElem = getChild(pmdModelElem, "boneList");\r
-\r
-        List<BoneInfo> boneList = this.model.getBoneList();\r
-\r
-        for(Element boneElem : eachChild(boneListElem, "bone")){\r
-            BoneInfo boneInfo = new BoneInfo();\r
-            boneList.add(boneInfo);\r
-\r
-            I18nText boneName = boneInfo.getBoneName();\r
-            buildI18nName(boneElem, boneName);\r
-\r
-            String boneType = getStringAttr(boneElem, "type");\r
-            BoneType type = BoneType.valueOf(boneType);\r
-            boneInfo.setBoneType(type);\r
-\r
-            String boneId = getStringAttr(boneElem, "boneId");\r
-            this.boneMap.put(boneId, boneInfo);\r
-\r
-            Element positionElem = getChild(boneElem, "position");\r
-            float xPos = getFloatAttr(positionElem, "x");\r
-            float yPos = getFloatAttr(positionElem, "y");\r
-            float zPos = getFloatAttr(positionElem, "z");\r
-            Pos3d position = boneInfo.getPosition();\r
-            position.setXPos(xPos);\r
-            position.setYPos(yPos);\r
-            position.setZPos(zPos);\r
-        }\r
-\r
-        ListUtil.assignIndexedSerial(boneList);\r
-\r
-        int serial = 0;\r
-        for(Element boneElem : eachChild(boneListElem, "bone")){\r
-            BoneInfo boneInfo = boneList.get(serial++);\r
-\r
-            if(hasChild(boneElem, "ikBone")){\r
-                Element ikBoneElem = getChild(boneElem, "ikBone");\r
-                String ikBoneId = getStringAttr(ikBoneElem, "boneIdRef");\r
-                BoneInfo ikBone = this.boneMap.get(ikBoneId);\r
-                boneInfo.setIKBone(ikBone);\r
-            }else if(hasChild(boneElem, "rotationRatio")){\r
-                Element ikBoneElem = getChild(boneElem, "rotationRatio");\r
-                int ratio = getIntegerAttr(ikBoneElem, "ratio");\r
-                boneInfo.setRotationRatio(ratio);\r
-            }\r
-\r
-            Element boneChainElem = getChild(boneElem, "boneChain");\r
-            if(boneChainElem.hasAttribute("prevBoneIdRef")){\r
-                String prevId = getStringAttr(boneChainElem, "prevBoneIdRef");\r
-                BoneInfo prevBone = this.boneMap.get(prevId);\r
-                boneInfo.setPrevBone(prevBone);\r
-            }\r
-            if(boneChainElem.hasAttribute("nextBoneIdRef")){\r
-                String nextId = getStringAttr(boneChainElem, "nextBoneIdRef");\r
-                BoneInfo nextBone = this.boneMap.get(nextId);\r
-                boneInfo.setNextBone(nextBone);\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildVertexList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element vertexListElem = getChild(pmdModelElem, "vertexList");\r
-\r
-        List<Vertex> vertexList = this.model.getVertexList();\r
-\r
-        for(Element vertexElem : eachChild(vertexListElem, "vertex")){\r
-            Vertex vertex = new Vertex();\r
-            vertexList.add(vertex);\r
-\r
-            String vertexId = getStringAttr(vertexElem, "vtxId");\r
-            this.vertexMap.put(vertexId, vertex);\r
-\r
-            boolean showEdge = getBooleanAttr(vertexElem, "showEdge");\r
-            vertex.setEdgeAppearance(showEdge);\r
-\r
-            float xVal;\r
-            float yVal;\r
-            float zVal;\r
-\r
-            Element positionElem = getChild(vertexElem, "position");\r
-            xVal = getFloatAttr(positionElem, "x");\r
-            yVal = getFloatAttr(positionElem, "y");\r
-            zVal = getFloatAttr(positionElem, "z");\r
-            Pos3d position = vertex.getPosition();\r
-            position.setXPos(xVal);\r
-            position.setYPos(yVal);\r
-            position.setZPos(zVal);\r
-\r
-            Element normalElem = getChild(vertexElem, "normal");\r
-            xVal = getFloatAttr(normalElem, "x");\r
-            yVal = getFloatAttr(normalElem, "y");\r
-            zVal = getFloatAttr(normalElem, "z");\r
-            Vec3d normal = vertex.getNormal();\r
-            normal.setXVal(xVal);\r
-            normal.setYVal(yVal);\r
-            normal.setZVal(zVal);\r
-\r
-            Element uvElem = getChild(vertexElem, "uvMap");\r
-            float uVal = getFloatAttr(uvElem, "u");\r
-            float vVal = getFloatAttr(uvElem, "v");\r
-            Pos2d uv = vertex.getUVPosition();\r
-            uv.setXPos(uVal);\r
-            uv.setYPos(vVal);\r
-\r
-            Element skinningElem = getChild(vertexElem, "skinning");\r
-            String boneId1 = getStringAttr(skinningElem, "boneIdRef1");\r
-            String boneId2 = getStringAttr(skinningElem, "boneIdRef2");\r
-            int weight = getIntegerAttr(skinningElem, "weightBalance");\r
-            BoneInfo boneA = this.boneMap.get(boneId1);\r
-            BoneInfo boneB = this.boneMap.get(boneId2);\r
-            vertex.setBonePair(boneA, boneB);\r
-            vertex.setWeightA(weight);\r
-        }\r
-\r
-        ListUtil.assignIndexedSerial(vertexList);\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildSurfaceList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element surfaceGroupListElem =\r
-                getChild(pmdModelElem, "surfaceGroupList");\r
-\r
-        for(Element surfaceGroupElem :\r
-            eachChild(surfaceGroupListElem, "surfaceGroup") ){\r
-\r
-            String groupId =\r
-                    getStringAttr(surfaceGroupElem, "surfaceGroupId");\r
-            List<Surface> surfaceList = buildSurface(surfaceGroupElem);\r
-\r
-            this.surfaceGroupMap.put(groupId, surfaceList);\r
-        }\r
-    }\r
-\r
-    private List<Surface> buildSurface(Element surfaceGroupElem)\r
-            throws TogaXmlException{\r
-        List<Surface> result = new ArrayList<Surface>();\r
-\r
-        for(Element surfaceElem : eachChild(surfaceGroupElem, "surface")){\r
-            Surface surface = new Surface();\r
-            result.add(surface);\r
-\r
-            String id1 = getStringAttr(surfaceElem, "vtxIdRef1");\r
-            String id2 = getStringAttr(surfaceElem, "vtxIdRef2");\r
-            String id3 = getStringAttr(surfaceElem, "vtxIdRef3");\r
-\r
-            Vertex vertex1 = this.vertexMap.get(id1);\r
-            Vertex vertex2 = this.vertexMap.get(id2);\r
-            Vertex vertex3 = this.vertexMap.get(id3);\r
-\r
-            surface.setTriangle(vertex1, vertex2, vertex3);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    private void buildMaterialList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element materialListElem =\r
-                getChild(pmdModelElem, "materialList");\r
-\r
-        List<Surface> surfaceList = this.model.getSurfaceList();\r
-        List<Material> materialList = this.model.getMaterialList();\r
-\r
-        for(Element materialElem : eachChild(materialListElem, "material")){\r
-            Material material = new Material();\r
-            materialList.add(material);\r
-\r
-            material.getShadeInfo().setToonMap(this.model.getToonMap());\r
-\r
-            String surfaceGroupId =\r
-                    getStringAttr(materialElem, "surfaceGroupIdRef");\r
-            List<Surface> surfaceGroup =\r
-                    this.surfaceGroupMap.get(surfaceGroupId);\r
-            surfaceList.addAll(surfaceGroup);\r
-            material.getSurfaceList().addAll(surfaceGroup);\r
-\r
-            boolean hasEdge = getBooleanAttr(materialElem, "showEdge");\r
-            material.setEdgeAppearance(hasEdge);\r
-\r
-            ShadeInfo shadeInfo = material.getShadeInfo();\r
-\r
-            int toonIdx;\r
-            if(hasChild(materialElem, "toon")){\r
-                Element toonElem = getChild(materialElem, "toon");\r
-                String toonId = getStringAttr(toonElem, "toonFileIdRef");\r
-                toonIdx = this.toonIdxMap.get(toonId);\r
-            }else{\r
-                toonIdx = 255;\r
-            }\r
-            shadeInfo.setToonIndex(toonIdx);\r
-\r
-            if(hasChild(materialElem, "textureFile")){\r
-                Element textureFileElem =\r
-                        getChild(materialElem, "textureFile");\r
-                String textureFile =\r
-                        getSjisFileNameAttr(textureFileElem, "winFileName");\r
-                shadeInfo.setTextureFileName(textureFile);\r
-            }\r
-\r
-            if(hasChild(materialElem, "spheremapFile")){\r
-                Element spheremapFileElem =\r
-                        getChild(materialElem, "spheremapFile");\r
-                String spheremapFile =\r
-                        getSjisFileNameAttr(spheremapFileElem, "winFileName");\r
-                shadeInfo.setSpheremapFileName(spheremapFile);\r
-            }\r
-\r
-            float red;\r
-            float green;\r
-            float blue;\r
-\r
-            Element diffuseElem = getChild(materialElem, "diffuse");\r
-            red   = getFloatAttr(diffuseElem, "r");\r
-            green = getFloatAttr(diffuseElem, "g");\r
-            blue  = getFloatAttr(diffuseElem, "b");\r
-            float alpha = getFloatAttr(diffuseElem, "alpha");\r
-            Color diffuse = new Color(red, green, blue, alpha);\r
-            material.setDiffuseColor(diffuse);\r
-\r
-            Element specularElem = getChild(materialElem, "specular");\r
-            red   = getFloatAttr(specularElem, "r");\r
-            green = getFloatAttr(specularElem, "g");\r
-            blue  = getFloatAttr(specularElem, "b");\r
-            float shininess = getFloatAttr(specularElem, "shininess");\r
-            Color specular = new Color(red, green, blue);\r
-            material.setSpecularColor(specular);\r
-            material.setShininess(shininess);\r
-\r
-            Element ambientElem = getChild(materialElem, "ambient");\r
-            red   = getFloatAttr(ambientElem, "r");\r
-            green = getFloatAttr(ambientElem, "g");\r
-            blue  = getFloatAttr(ambientElem, "b");\r
-            Color ambient = new Color(red, green, blue);\r
-            material.setAmbientColor(ambient);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildIkChainList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element ikChainListElem =\r
-                getChild(pmdModelElem, "ikChainList");\r
-\r
-        List<IKChain> ikChainList = this.model.getIKChainList();\r
-\r
-        for(Element ikChainElem : eachChild(ikChainListElem, "ikChain")){\r
-            IKChain ikChain = new IKChain();\r
-            ikChainList.add(ikChain);\r
-\r
-            String ikBoneIdRef = getStringAttr(ikChainElem, "ikBoneIdRef");\r
-            int rucursiveDepth =\r
-                    getIntegerAttr(ikChainElem, "recursiveDepth");\r
-            float weight = getFloatAttr(ikChainElem, "weight");\r
-\r
-            BoneInfo ikBone = this.boneMap.get(ikBoneIdRef);\r
-            ikChain.setIkBone(ikBone);\r
-            ikChain.setIKDepth(rucursiveDepth);\r
-            ikChain.setIKWeight(weight);\r
-\r
-            List<BoneInfo> chainList = ikChain.getChainedBoneList();\r
-\r
-            for(Element orderElem : eachChild(ikChainElem, "chainOrder")){\r
-                String boneIdRef = getStringAttr(orderElem, "boneIdRef");\r
-                BoneInfo chaindBone = this.boneMap.get(boneIdRef);\r
-                chainList.add(chaindBone);\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildMorphList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element morphListElem =\r
-                getChild(pmdModelElem, "morphList");\r
-\r
-        Map<MorphType, List<MorphPart>> morphMap = this.model.getMorphMap();\r
-\r
-        for(Element morphElem : eachChild(morphListElem, "morph")){\r
-            MorphPart morphPart = new MorphPart();\r
-\r
-            I18nText name = morphPart.getMorphName();\r
-            buildI18nName(morphElem, name);\r
-\r
-            String type = getStringAttr(morphElem, "type");\r
-            MorphType morphType = MorphType.valueOf(type);\r
-            morphPart.setMorphType(morphType);\r
-\r
-            List<MorphVertex> morphVertexList =\r
-                    morphPart.getMorphVertexList();\r
-\r
-            for(Element morphVertexElem\r
-                    : eachChild(morphElem, "morphVertex")){\r
-                String vtxIdRef = getStringAttr(morphVertexElem, "vtxIdRef");\r
-                Vertex baseVertex = this.vertexMap.get(vtxIdRef);\r
-                float xOff = getFloatAttr(morphVertexElem, "xOff");\r
-                float yOff = getFloatAttr(morphVertexElem, "yOff");\r
-                float zOff = getFloatAttr(morphVertexElem, "zOff");\r
-\r
-                MorphVertex morphVertex = new MorphVertex();\r
-                morphVertex.setBaseVertex(baseVertex);\r
-                Pos3d position = morphVertex.getOffset();\r
-                position.setXPos(xOff);\r
-                position.setYPos(yOff);\r
-                position.setZPos(zOff);\r
-\r
-                morphVertexList.add(morphVertex);\r
-            }\r
-\r
-            morphMap.get(morphType).add(morphPart);\r
-        }\r
-\r
-        List<MorphPart> serialList = new LinkedList<MorphPart>();\r
-        MorphPart baseDummy = new MorphPart();\r
-        serialList.add(baseDummy);\r
-        for(MorphPart part : morphMap.get(MorphType.EYEBROW)){\r
-            serialList.add(part);\r
-        }\r
-        for(MorphPart part : morphMap.get(MorphType.EYE)){\r
-            serialList.add(part);\r
-        }\r
-        for(MorphPart part : morphMap.get(MorphType.LIP)){\r
-            serialList.add(part);\r
-        }\r
-        for(MorphPart part : morphMap.get(MorphType.EXTRA)){\r
-            serialList.add(part);\r
-        }\r
-        ListUtil.assignIndexedSerial(serialList);\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildBoneGroupList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element boneGroupListElem =\r
-                getChild(pmdModelElem, "boneGroupList");\r
-\r
-        List<BoneGroup> boneGroupList = this.model.getBoneGroupList();\r
-        BoneGroup defaultGroup = new BoneGroup();\r
-        boneGroupList.add(defaultGroup);\r
-\r
-        for(Element boneGroupElem\r
-                : eachChild(boneGroupListElem, "boneGroup")){\r
-            BoneGroup group = new BoneGroup();\r
-            boneGroupList.add(group);\r
-\r
-            I18nText name = group.getGroupName();\r
-            buildI18nName(boneGroupElem, name);\r
-\r
-            for(Element boneGroupMemberElem\r
-                    : eachChild(boneGroupElem, "boneGroupMember")){\r
-                String boneIdRef =\r
-                        getStringAttr(boneGroupMemberElem, "boneIdRef");\r
-                BoneInfo bone = this.boneMap.get(boneIdRef);\r
-                group.getBoneList().add(bone);\r
-            }\r
-        }\r
-\r
-        ListUtil.assignIndexedSerial(boneGroupList);\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildRigidList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element rigidListElem =\r
-                getChild(pmdModelElem, "rigidList");\r
-\r
-        List<RigidInfo> rigidList = this.model.getRigidList();\r
-\r
-        for(Element rigidElem : eachChild(rigidListElem, "rigid")){\r
-            RigidInfo rigid = new RigidInfo();\r
-            rigidList.add(rigid);\r
-\r
-            I18nText name = rigid.getRigidName();\r
-            buildI18nName(rigidElem, name);\r
-\r
-            String behavior = getStringAttr(rigidElem, "behavior");\r
-            RigidBehaviorType type = RigidBehaviorType.valueOf(behavior);\r
-            rigid.setBehaviorType(type);\r
-\r
-            String rigidId = getStringAttr(rigidElem, "rigidId");\r
-            this.rigidMap.put(rigidId, rigid);\r
-\r
-            if(hasChild(rigidElem, "linkedBone")){\r
-                Element linkedBoneElem = getChild(rigidElem, "linkedBone");\r
-                String boneIdRef = getStringAttr(linkedBoneElem, "boneIdRef");\r
-                BoneInfo linkedBone = this.boneMap.get(boneIdRef);\r
-                rigid.setLinkedBone(linkedBone);\r
-            }\r
-\r
-            RigidShape rigidShape = rigid.getRigidShape();\r
-            if(hasChild(rigidElem, "rigidShapeSphere")){\r
-                Element shapeElem =\r
-                        getChild(rigidElem, "rigidShapeSphere");\r
-                float radius = getFloatAttr(shapeElem, "radius");\r
-                rigidShape.setShapeType(RigidShapeType.SPHERE);\r
-                rigidShape.setRadius(radius);\r
-            }\r
-            if(hasChild(rigidElem, "rigidShapeBox")){\r
-                Element shapeElem =\r
-                        getChild(rigidElem, "rigidShapeBox");\r
-                float width  = getFloatAttr(shapeElem, "width");\r
-                float height = getFloatAttr(shapeElem, "height");\r
-                float depth  = getFloatAttr(shapeElem, "depth");\r
-                rigidShape.setShapeType(RigidShapeType.BOX);\r
-                rigidShape.setWidth(width);\r
-                rigidShape.setHeight(height);\r
-                rigidShape.setDepth(depth);\r
-            }\r
-            if(hasChild(rigidElem, "rigidShapeCapsule")){\r
-                Element shapeElem =\r
-                        getChild(rigidElem, "rigidShapeCapsule");\r
-                float height = getFloatAttr(shapeElem, "height");\r
-                float radius = getFloatAttr(shapeElem, "radius");\r
-                rigidShape.setShapeType(RigidShapeType.CAPSULE);\r
-                rigidShape.setHeight(height);\r
-                rigidShape.setRadius(radius);\r
-            }\r
-\r
-            float xVal;\r
-            float yVal;\r
-            float zVal;\r
-\r
-            Element positionElem = getChild(rigidElem, "position");\r
-            xVal = getFloatAttr(positionElem, "x");\r
-            yVal = getFloatAttr(positionElem, "y");\r
-            zVal = getFloatAttr(positionElem, "z");\r
-            Pos3d position = rigid.getPosition();\r
-            position.setXPos(xVal);\r
-            position.setYPos(yVal);\r
-            position.setZPos(zVal);\r
-\r
-            Element radRotationElem = getChild(rigidElem, "radRotation");\r
-            xVal = getFloatAttr(radRotationElem, "xRad");\r
-            yVal = getFloatAttr(radRotationElem, "yRad");\r
-            zVal = getFloatAttr(radRotationElem, "zRad");\r
-            Rad3d rotation = rigid.getRotation();\r
-            rotation.setXRad(xVal);\r
-            rotation.setYRad(yVal);\r
-            rotation.setZRad(zVal);\r
-\r
-            Element dynamicsElem = getChild(rigidElem, "dynamics");\r
-            float mass = getFloatAttr(dynamicsElem, "mass");\r
-            float dampingPosition =\r
-                    getFloatAttr(dynamicsElem, "dampingPosition");\r
-            float dampingRotation =\r
-                    getFloatAttr(dynamicsElem, "dampingRotation");\r
-            float restitution = getFloatAttr(dynamicsElem, "restitution");\r
-            float friction = getFloatAttr(dynamicsElem, "friction");\r
-            DynamicsInfo dynamics = rigid.getDynamicsInfo();\r
-            dynamics.setMass(mass);\r
-            dynamics.setDampingPosition(dampingPosition);\r
-            dynamics.setDampingRotation(dampingRotation);\r
-            dynamics.setRestitution(restitution);\r
-            dynamics.setFriction(friction);\r
-        }\r
-\r
-        ListUtil.assignIndexedSerial(rigidList);\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildRigidGroupList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element rigidGroupListElem =\r
-                getChild(pmdModelElem, "rigidGroupList");\r
-\r
-        List<RigidGroup> groupList = this.model.getRigidGroupList();\r
-\r
-        for(Element rigidGroupElem\r
-                : eachChild(rigidGroupListElem, "rigidGroup")){\r
-            RigidGroup rigidGroup = new RigidGroup();\r
-            groupList.add(rigidGroup);\r
-\r
-            String rigidGroupId =\r
-                    getStringAttr(rigidGroupElem, "rigidGroupId");\r
-            this.rigidGroupMap.put(rigidGroupId, rigidGroup);\r
-\r
-            for(Element memberElem\r
-                    : eachChild(rigidGroupElem, "rigidGroupMember")){\r
-                String rigidIdRef = getStringAttr(memberElem, "rigidIdRef");\r
-                RigidInfo rigid = this.rigidMap.get(rigidIdRef);\r
-                rigidGroup.getRigidList().add(rigid);\r
-                rigid.setRigidGroup(rigidGroup);\r
-            }\r
-        }\r
-\r
-        while(groupList.size() < 16){\r
-            RigidGroup rigidGroup = new RigidGroup();\r
-            groupList.add(rigidGroup);\r
-        }\r
-\r
-        ListUtil.assignIndexedSerial(groupList);\r
-\r
-        return;\r
-    }\r
-\r
-    private void resolveThroughRigidGroup(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element rigidListElem =\r
-                getChild(pmdModelElem, "rigidList");\r
-\r
-        List<RigidInfo> rigidList = this.model.getRigidList();\r
-\r
-        int serialNum = 0;\r
-        for(Element rigidElem : eachChild(rigidListElem, "rigid")){\r
-            RigidInfo rigid = rigidList.get(serialNum++);\r
-            for(Element groupElem\r
-                    : eachChild(rigidElem, "throughRigidGroup")){\r
-                String groupId = getStringAttr(groupElem, "rigidGroupIdRef");\r
-                RigidGroup group = this.rigidGroupMap.get(groupId);\r
-                rigid.getThroughGroupColl().add(group);\r
-            }\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    private void buildJointList(Element pmdModelElem)\r
-            throws TogaXmlException{\r
-        Element jointListElem =\r
-                getChild(pmdModelElem, "jointList");\r
-\r
-        List<JointInfo> jointList = this.model.getJointList();\r
-\r
-        for(Element jointElem : eachChild(jointListElem, "joint")){\r
-            JointInfo joint = new JointInfo();\r
-            jointList.add(joint);\r
-\r
-            I18nText name = joint.getJointName();\r
-            buildI18nName(jointElem, name);\r
-\r
-            Element rigidPairElem = getChild(jointElem, "jointedRigidPair");\r
-            String rigidIdRef1 = getStringAttr(rigidPairElem, "rigidIdRef1");\r
-            String rigidIdRef2 = getStringAttr(rigidPairElem, "rigidIdRef2");\r
-            RigidInfo rigid1 = this.rigidMap.get(rigidIdRef1);\r
-            RigidInfo rigid2 = this.rigidMap.get(rigidIdRef2);\r
-            joint.setRigidPair(rigid1, rigid2);\r
-\r
-            float xVal;\r
-            float yVal;\r
-            float zVal;\r
-            float xFrom;\r
-            float xTo;\r
-            float yFrom;\r
-            float yTo;\r
-            float zFrom;\r
-            float zTo;\r
-\r
-            Pos3d position = joint.getPosition();\r
-            Element positionElem = getChild(jointElem, "position");\r
-            xVal = getFloatAttr(positionElem, "x");\r
-            yVal = getFloatAttr(positionElem, "y");\r
-            zVal = getFloatAttr(positionElem, "z");\r
-            position.setXPos(xVal);\r
-            position.setYPos(yVal);\r
-            position.setZPos(zVal);\r
-\r
-            TripletRange limitPosition = joint.getPositionRange();\r
-            Element limitPositionElem = getChild(jointElem, "limitPosition");\r
-            xFrom = getFloatAttr(limitPositionElem, "xFrom");\r
-            xTo   = getFloatAttr(limitPositionElem, "xTo");\r
-            yFrom = getFloatAttr(limitPositionElem, "yFrom");\r
-            yTo   = getFloatAttr(limitPositionElem, "yTo");\r
-            zFrom = getFloatAttr(limitPositionElem, "zFrom");\r
-            zTo   = getFloatAttr(limitPositionElem, "zTo");\r
-            limitPosition.setXRange(xFrom, xTo);\r
-            limitPosition.setYRange(yFrom, yTo);\r
-            limitPosition.setZRange(zFrom, zTo);\r
-\r
-            Rad3d rotation = joint.getRotation();\r
-            Element rotationElem = getChild(jointElem, "radRotation");\r
-            xVal = getFloatAttr(rotationElem, "xRad");\r
-            yVal = getFloatAttr(rotationElem, "yRad");\r
-            zVal = getFloatAttr(rotationElem, "zRad");\r
-            rotation.setXRad(xVal);\r
-            rotation.setYRad(yVal);\r
-            rotation.setZRad(zVal);\r
-\r
-            TripletRange limitRotation = joint.getRotationRange();\r
-            Element limitRotationElem = getChild(jointElem, "limitRotation");\r
-            xFrom = getFloatAttr(limitRotationElem, "xFrom");\r
-            xTo   = getFloatAttr(limitRotationElem, "xTo");\r
-            yFrom = getFloatAttr(limitRotationElem, "yFrom");\r
-            yTo   = getFloatAttr(limitRotationElem, "yTo");\r
-            zFrom = getFloatAttr(limitRotationElem, "zFrom");\r
-            zTo   = getFloatAttr(limitRotationElem, "zTo");\r
-            limitRotation.setXRange(xFrom, xTo);\r
-            limitRotation.setYRange(yFrom, yTo);\r
-            limitRotation.setZRange(zFrom, zTo);\r
-\r
-            Pos3d elasticPosition = joint.getElasticPosition();\r
-            Element elasticPositionElem =\r
-                    getChild(jointElem, "elasticPosition");\r
-            xVal = getFloatAttr(elasticPositionElem, "x");\r
-            yVal = getFloatAttr(elasticPositionElem, "y");\r
-            zVal = getFloatAttr(elasticPositionElem, "z");\r
-            elasticPosition.setXPos(xVal);\r
-            elasticPosition.setYPos(yVal);\r
-            elasticPosition.setZPos(zVal);\r
-\r
-            Deg3d elasticRotation = joint.getElasticRotation();\r
-            Element elasticRotationElem =\r
-                    getChild(jointElem, "elasticRotation");\r
-            xVal = getFloatAttr(elasticRotationElem, "xDeg");\r
-            yVal = getFloatAttr(elasticRotationElem, "yDeg");\r
-            zVal = getFloatAttr(elasticRotationElem, "zDeg");\r
-            elasticRotation.setXDeg(xVal);\r
-            elasticRotation.setYDeg(yVal);\r
-            elasticRotation.setZDeg(zVal);\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * xml loader
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd.xml;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import jp.sourceforge.mikutoga.corelib.I18nText;
+import jp.sourceforge.mikutoga.corelib.ListUtil;
+import jp.sourceforge.mikutoga.pmd.BoneGroup;
+import jp.sourceforge.mikutoga.pmd.BoneInfo;
+import jp.sourceforge.mikutoga.pmd.BoneType;
+import jp.sourceforge.mikutoga.pmd.Deg3d;
+import jp.sourceforge.mikutoga.pmd.DynamicsInfo;
+import jp.sourceforge.mikutoga.pmd.IKChain;
+import jp.sourceforge.mikutoga.pmd.JointInfo;
+import jp.sourceforge.mikutoga.pmd.Material;
+import jp.sourceforge.mikutoga.pmd.MorphPart;
+import jp.sourceforge.mikutoga.pmd.MorphType;
+import jp.sourceforge.mikutoga.pmd.MorphVertex;
+import jp.sourceforge.mikutoga.pmd.PmdModel;
+import jp.sourceforge.mikutoga.pmd.Pos2d;
+import jp.sourceforge.mikutoga.pmd.Pos3d;
+import jp.sourceforge.mikutoga.pmd.Rad3d;
+import jp.sourceforge.mikutoga.pmd.RigidBehaviorType;
+import jp.sourceforge.mikutoga.pmd.RigidGroup;
+import jp.sourceforge.mikutoga.pmd.RigidInfo;
+import jp.sourceforge.mikutoga.pmd.RigidShape;
+import jp.sourceforge.mikutoga.pmd.RigidShapeType;
+import jp.sourceforge.mikutoga.pmd.ShadeInfo;
+import jp.sourceforge.mikutoga.pmd.Surface;
+import jp.sourceforge.mikutoga.pmd.ToonMap;
+import jp.sourceforge.mikutoga.pmd.TripletRange;
+import jp.sourceforge.mikutoga.pmd.Vec3d;
+import jp.sourceforge.mikutoga.pmd.Vertex;
+import jp.sourceforge.mikutoga.xml.DomUtils;
+import jp.sourceforge.mikutoga.xml.TogaXmlException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * XML形式でのモデルファイルを読み込む。
+ */
+public class Xml2PmdLoader {
+
+    private final DocumentBuilder builder;
+
+    private PmdModel model;
+
+    private final Map<String, Integer> toonIdxMap =
+            new HashMap<String, Integer>();
+    private final Map<String, BoneInfo> boneMap =
+            new HashMap<String, BoneInfo>();
+    private final Map<String, Vertex> vertexMap =
+            new HashMap<String, Vertex>();
+    private final Map<String, List<Surface>> surfaceGroupMap =
+            new HashMap<String, List<Surface>>();
+    private final Map<String, RigidInfo> rigidMap =
+            new HashMap<String, RigidInfo>();
+    private final Map<String, RigidGroup> rigidGroupMap =
+            new HashMap<String, RigidGroup>();
+
+
+    /**
+     * コンストラクタ。
+     * @param builder ビルダ
+     */
+    public Xml2PmdLoader(DocumentBuilder builder){
+        super();
+        this.builder = builder;
+        return;
+    }
+
+    /**
+     * 要素からxsd:string型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return 文字列
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    private static String getStringAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        return DomUtils.getStringAttr(elem, attrName);
+    }
+
+    /**
+     * 要素からxsd:boolean型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return 真ならtrue
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    private static boolean getBooleanAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        return DomUtils.getBooleanAttr(elem, attrName);
+    }
+
+    /**
+     * 要素からxsd:integer型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return int値
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    private static int getIntegerAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        return DomUtils.getIntegerAttr(elem, attrName);
+    }
+
+    /**
+     * 要素からxsd:float型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return float値
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    private static float getFloatAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        return DomUtils.getFloatAttr(elem, attrName);
+    }
+
+    /**
+     * 要素から日本語Windows用ファイル名を属性値として読み取る。
+     * 念のため文字U+00A5は文字U-005Cに変換される。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return ファイル名
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    private static String getSjisFileNameAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        return DomUtils.getSjisFileNameAttr(elem, attrName);
+    }
+
+    /**
+     * 指定された名前の子要素を1つだけ返す。
+     * @param parent 親要素
+     * @param tagName 子要素名
+     * @return 子要素
+     * @throws TogaXmlException 1つも見つからなかった
+     */
+    private static Element getChild(Element parent, String tagName)
+            throws TogaXmlException{
+        return DomUtils.getChild(parent, tagName);
+    }
+
+    /**
+     * 親要素が指定された名前の子要素を持つか判定する。
+     * @param parent 親要素
+     * @param tagName 子要素名
+     * @return 指定名の子要素が存在すればtrue
+     */
+    private static boolean hasChild(Element parent, String tagName){
+        return DomUtils.hasChild(parent, tagName);
+    }
+
+    /**
+     * 指定された名前の子要素のforeachを返す。
+     * @param parent 親要素
+     * @param childTag 子要素名
+     * @return 子要素のforeach
+     */
+    private static Iterable<Element> eachChild(Element parent,
+                                                    String childTag){
+        return DomUtils.getEachChild(parent, childTag);
+    }
+
+    /**
+     * グローバル名を取得する。
+     * 元要素のname属性及びi18nNameタグを持つ子要素が検索対象
+     * @param parent 元要素
+     * @return グローバル名。なければnull
+     */
+    private static String getGlobalName(Element parent){
+        NodeList nodeList = parent.getElementsByTagName("i18nName");
+        int length = nodeList.getLength();
+        for(int idx = 0; idx < length; idx++){
+            Node i18nNameNode = nodeList.item(idx);
+            Element i18nNameElem = (Element)i18nNameNode;
+            String lang = i18nNameElem.getAttribute("lang");
+            if(lang == null || lang.length() <= 0) continue;
+            if(lang.equals("en")){
+                String name = i18nNameElem.getAttribute("name");
+                return name;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * brタグで区切られた文字列内容(Mixed content)を改行付き文字列に変換する。
+     * brタグはその出現回数だけ\nに変換される。
+     * 生文字列コンテンツ中の\n,\rは削除される。
+     * 改行文字以外のホワイトスペースは保持される。
+     * @param parent br要素及び文字列コンテンツを含む要素
+     * @return 変換された文字列
+     */
+    private static String getBRedContent(Element parent){
+        StringBuilder result = new StringBuilder();
+
+        for(Node node = parent.getFirstChild();
+            node != null;
+            node = node.getNextSibling() ){
+
+            switch(node.getNodeType()){
+            case Node.ELEMENT_NODE:
+                Element elem = (Element) node;
+                if("br".equals(elem.getTagName())){
+                    result.append('\n');
+                }
+                break;
+            case Node.TEXT_NODE:
+            case Node.CDATA_SECTION_NODE:
+                String content = node.getTextContent();
+                content = content.replace("\r", "");
+                content = content.replace("\n", "");
+                result.append(content);
+                break;
+            default:
+                break;
+            }
+        }
+
+        return result.toString();
+    }
+
+    /**
+     * 多言語名を取得する。
+     * @param baseElement 元要素
+     * @param text 多言語名
+     * @throws TogaXmlException あるべき属性が存在しない。
+     */
+    private static void buildI18nName(Element baseElement, I18nText text)
+            throws TogaXmlException{
+        String primaryText;
+        primaryText = getStringAttr(baseElement, "name");
+        text.setPrimaryText(primaryText);
+
+        for(Element i18nNameElem : eachChild(baseElement, "i18nName")){
+            String lang = getStringAttr(i18nNameElem, "lang");
+            String name = getStringAttr(i18nNameElem, "name");
+            if("en".equals(lang)){
+                text.setGlobalText(name);
+            }else{
+                text.setText(lang, text);
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * XMLのパースを開始する。
+     * @param source XML入力
+     * @return モデルデータ
+     * @throws SAXException 構文エラー
+     * @throws IOException 入力エラー
+     * @throws TogaXmlException 構文エラー
+     */
+    public PmdModel parse(InputSource source)
+            throws SAXException, IOException, TogaXmlException{
+        Document document = this.builder.parse(source);
+
+        this.model = new PmdModel();
+
+        Element pmdModelElem = document.getDocumentElement();
+
+        buildBasicInfo(pmdModelElem);
+
+        buildBoneList(pmdModelElem);
+        buildVertexList(pmdModelElem);
+        buildSurfaceList(pmdModelElem);
+
+        buildToonMap(pmdModelElem);
+        buildMaterialList(pmdModelElem);
+        buildIkChainList(pmdModelElem);
+        buildMorphList(pmdModelElem);
+        buildBoneGroupList(pmdModelElem);
+
+        buildRigidList(pmdModelElem);
+        buildRigidGroupList(pmdModelElem);
+        resolveThroughRigidGroup(pmdModelElem);
+
+        buildJointList(pmdModelElem);
+
+        return this.model;
+    }
+
+    private void buildBasicInfo(Element pmdModelElem)
+            throws TogaXmlException{
+        String primaryName = getStringAttr(pmdModelElem, "name");
+        String globalName = getGlobalName(pmdModelElem);
+
+        I18nText modelName = this.model.getModelName();
+        modelName.setPrimaryText(primaryName);
+        modelName.setGlobalText(globalName);
+
+        String primaryDescription = null;
+        String globalDescription = null;
+        for(Element descriptionElem :
+            eachChild(pmdModelElem, "description")){
+            String descriptionText = getBRedContent(descriptionElem);
+            if( ! descriptionElem.hasAttribute("lang") ){
+                primaryDescription = descriptionText;
+            }else{
+                String lang = getStringAttr(descriptionElem, "lang");
+                if(lang.equals("ja")){
+                    primaryDescription = descriptionText;
+                }else if(lang.equals("en")){
+                    globalDescription = descriptionText;
+                }
+            }
+        }
+
+        I18nText description = this.model.getDescription();
+        description.setPrimaryText(primaryDescription);
+        description.setGlobalText(globalDescription);
+
+        return;
+    }
+
+    private void buildToonMap(Element pmdModelElem)
+            throws TogaXmlException{
+        ToonMap toonMap = this.model.getToonMap();
+
+        Element toonMapElem = getChild(pmdModelElem, "toonMap");
+
+        for(Element toonDefElem : eachChild(toonMapElem, "toonDef")){
+            String toonFileId = getStringAttr(toonDefElem, "toonFileId");
+            int toonIndex = getIntegerAttr(toonDefElem, "index");
+            String toonFile = getSjisFileNameAttr(toonDefElem, "winFileName");
+
+            toonMap.setIndexedToon(toonIndex, toonFile);
+            this.toonIdxMap.put(toonFileId, toonIndex);
+        }
+
+        return;
+    }
+
+    private void buildBoneList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element boneListElem = getChild(pmdModelElem, "boneList");
+
+        List<BoneInfo> boneList = this.model.getBoneList();
+
+        for(Element boneElem : eachChild(boneListElem, "bone")){
+            BoneInfo boneInfo = new BoneInfo();
+            boneList.add(boneInfo);
+
+            I18nText boneName = boneInfo.getBoneName();
+            buildI18nName(boneElem, boneName);
+
+            String boneType = getStringAttr(boneElem, "type");
+            BoneType type = BoneType.valueOf(boneType);
+            boneInfo.setBoneType(type);
+
+            String boneId = getStringAttr(boneElem, "boneId");
+            this.boneMap.put(boneId, boneInfo);
+
+            Element positionElem = getChild(boneElem, "position");
+            float xPos = getFloatAttr(positionElem, "x");
+            float yPos = getFloatAttr(positionElem, "y");
+            float zPos = getFloatAttr(positionElem, "z");
+            Pos3d position = boneInfo.getPosition();
+            position.setXPos(xPos);
+            position.setYPos(yPos);
+            position.setZPos(zPos);
+        }
+
+        ListUtil.assignIndexedSerial(boneList);
+
+        int serial = 0;
+        for(Element boneElem : eachChild(boneListElem, "bone")){
+            BoneInfo boneInfo = boneList.get(serial++);
+
+            if(hasChild(boneElem, "ikBone")){
+                Element ikBoneElem = getChild(boneElem, "ikBone");
+                String ikBoneId = getStringAttr(ikBoneElem, "boneIdRef");
+                BoneInfo ikBone = this.boneMap.get(ikBoneId);
+                boneInfo.setIKBone(ikBone);
+            }else if(hasChild(boneElem, "rotationRatio")){
+                Element ikBoneElem = getChild(boneElem, "rotationRatio");
+                int ratio = getIntegerAttr(ikBoneElem, "ratio");
+                boneInfo.setRotationRatio(ratio);
+            }
+
+            Element boneChainElem = getChild(boneElem, "boneChain");
+            if(boneChainElem.hasAttribute("prevBoneIdRef")){
+                String prevId = getStringAttr(boneChainElem, "prevBoneIdRef");
+                BoneInfo prevBone = this.boneMap.get(prevId);
+                boneInfo.setPrevBone(prevBone);
+            }
+            if(boneChainElem.hasAttribute("nextBoneIdRef")){
+                String nextId = getStringAttr(boneChainElem, "nextBoneIdRef");
+                BoneInfo nextBone = this.boneMap.get(nextId);
+                boneInfo.setNextBone(nextBone);
+            }
+        }
+
+        return;
+    }
+
+    private void buildVertexList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element vertexListElem = getChild(pmdModelElem, "vertexList");
+
+        List<Vertex> vertexList = this.model.getVertexList();
+
+        for(Element vertexElem : eachChild(vertexListElem, "vertex")){
+            Vertex vertex = new Vertex();
+            vertexList.add(vertex);
+
+            String vertexId = getStringAttr(vertexElem, "vtxId");
+            this.vertexMap.put(vertexId, vertex);
+
+            boolean showEdge = getBooleanAttr(vertexElem, "showEdge");
+            vertex.setEdgeAppearance(showEdge);
+
+            float xVal;
+            float yVal;
+            float zVal;
+
+            Element positionElem = getChild(vertexElem, "position");
+            xVal = getFloatAttr(positionElem, "x");
+            yVal = getFloatAttr(positionElem, "y");
+            zVal = getFloatAttr(positionElem, "z");
+            Pos3d position = vertex.getPosition();
+            position.setXPos(xVal);
+            position.setYPos(yVal);
+            position.setZPos(zVal);
+
+            Element normalElem = getChild(vertexElem, "normal");
+            xVal = getFloatAttr(normalElem, "x");
+            yVal = getFloatAttr(normalElem, "y");
+            zVal = getFloatAttr(normalElem, "z");
+            Vec3d normal = vertex.getNormal();
+            normal.setXVal(xVal);
+            normal.setYVal(yVal);
+            normal.setZVal(zVal);
+
+            Element uvElem = getChild(vertexElem, "uvMap");
+            float uVal = getFloatAttr(uvElem, "u");
+            float vVal = getFloatAttr(uvElem, "v");
+            Pos2d uv = vertex.getUVPosition();
+            uv.setXPos(uVal);
+            uv.setYPos(vVal);
+
+            Element skinningElem = getChild(vertexElem, "skinning");
+            String boneId1 = getStringAttr(skinningElem, "boneIdRef1");
+            String boneId2 = getStringAttr(skinningElem, "boneIdRef2");
+            int weight = getIntegerAttr(skinningElem, "weightBalance");
+            BoneInfo boneA = this.boneMap.get(boneId1);
+            BoneInfo boneB = this.boneMap.get(boneId2);
+            vertex.setBonePair(boneA, boneB);
+            vertex.setWeightA(weight);
+        }
+
+        ListUtil.assignIndexedSerial(vertexList);
+
+        return;
+    }
+
+    private void buildSurfaceList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element surfaceGroupListElem =
+                getChild(pmdModelElem, "surfaceGroupList");
+
+        for(Element surfaceGroupElem :
+            eachChild(surfaceGroupListElem, "surfaceGroup") ){
+
+            String groupId =
+                    getStringAttr(surfaceGroupElem, "surfaceGroupId");
+            List<Surface> surfaceList = buildSurface(surfaceGroupElem);
+
+            this.surfaceGroupMap.put(groupId, surfaceList);
+        }
+    }
+
+    private List<Surface> buildSurface(Element surfaceGroupElem)
+            throws TogaXmlException{
+        List<Surface> result = new ArrayList<Surface>();
+
+        for(Element surfaceElem : eachChild(surfaceGroupElem, "surface")){
+            Surface surface = new Surface();
+            result.add(surface);
+
+            String id1 = getStringAttr(surfaceElem, "vtxIdRef1");
+            String id2 = getStringAttr(surfaceElem, "vtxIdRef2");
+            String id3 = getStringAttr(surfaceElem, "vtxIdRef3");
+
+            Vertex vertex1 = this.vertexMap.get(id1);
+            Vertex vertex2 = this.vertexMap.get(id2);
+            Vertex vertex3 = this.vertexMap.get(id3);
+
+            surface.setTriangle(vertex1, vertex2, vertex3);
+        }
+
+        return result;
+    }
+
+    private void buildMaterialList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element materialListElem =
+                getChild(pmdModelElem, "materialList");
+
+        List<Surface> surfaceList = this.model.getSurfaceList();
+        List<Material> materialList = this.model.getMaterialList();
+
+        for(Element materialElem : eachChild(materialListElem, "material")){
+            Material material = new Material();
+            materialList.add(material);
+
+            material.getShadeInfo().setToonMap(this.model.getToonMap());
+
+            String surfaceGroupId =
+                    getStringAttr(materialElem, "surfaceGroupIdRef");
+            List<Surface> surfaceGroup =
+                    this.surfaceGroupMap.get(surfaceGroupId);
+            surfaceList.addAll(surfaceGroup);
+            material.getSurfaceList().addAll(surfaceGroup);
+
+            boolean hasEdge = getBooleanAttr(materialElem, "showEdge");
+            material.setEdgeAppearance(hasEdge);
+
+            ShadeInfo shadeInfo = material.getShadeInfo();
+
+            int toonIdx;
+            if(hasChild(materialElem, "toon")){
+                Element toonElem = getChild(materialElem, "toon");
+                String toonId = getStringAttr(toonElem, "toonFileIdRef");
+                toonIdx = this.toonIdxMap.get(toonId);
+            }else{
+                toonIdx = 255;
+            }
+            shadeInfo.setToonIndex(toonIdx);
+
+            if(hasChild(materialElem, "textureFile")){
+                Element textureFileElem =
+                        getChild(materialElem, "textureFile");
+                String textureFile =
+                        getSjisFileNameAttr(textureFileElem, "winFileName");
+                shadeInfo.setTextureFileName(textureFile);
+            }
+
+            if(hasChild(materialElem, "spheremapFile")){
+                Element spheremapFileElem =
+                        getChild(materialElem, "spheremapFile");
+                String spheremapFile =
+                        getSjisFileNameAttr(spheremapFileElem, "winFileName");
+                shadeInfo.setSpheremapFileName(spheremapFile);
+            }
+
+            float red;
+            float green;
+            float blue;
+
+            Element diffuseElem = getChild(materialElem, "diffuse");
+            red   = getFloatAttr(diffuseElem, "r");
+            green = getFloatAttr(diffuseElem, "g");
+            blue  = getFloatAttr(diffuseElem, "b");
+            float alpha = getFloatAttr(diffuseElem, "alpha");
+            Color diffuse = new Color(red, green, blue, alpha);
+            material.setDiffuseColor(diffuse);
+
+            Element specularElem = getChild(materialElem, "specular");
+            red   = getFloatAttr(specularElem, "r");
+            green = getFloatAttr(specularElem, "g");
+            blue  = getFloatAttr(specularElem, "b");
+            float shininess = getFloatAttr(specularElem, "shininess");
+            Color specular = new Color(red, green, blue);
+            material.setSpecularColor(specular);
+            material.setShininess(shininess);
+
+            Element ambientElem = getChild(materialElem, "ambient");
+            red   = getFloatAttr(ambientElem, "r");
+            green = getFloatAttr(ambientElem, "g");
+            blue  = getFloatAttr(ambientElem, "b");
+            Color ambient = new Color(red, green, blue);
+            material.setAmbientColor(ambient);
+        }
+
+        return;
+    }
+
+    private void buildIkChainList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element ikChainListElem =
+                getChild(pmdModelElem, "ikChainList");
+
+        List<IKChain> ikChainList = this.model.getIKChainList();
+
+        for(Element ikChainElem : eachChild(ikChainListElem, "ikChain")){
+            IKChain ikChain = new IKChain();
+            ikChainList.add(ikChain);
+
+            String ikBoneIdRef = getStringAttr(ikChainElem, "ikBoneIdRef");
+            int rucursiveDepth =
+                    getIntegerAttr(ikChainElem, "recursiveDepth");
+            float weight = getFloatAttr(ikChainElem, "weight");
+
+            BoneInfo ikBone = this.boneMap.get(ikBoneIdRef);
+            ikChain.setIkBone(ikBone);
+            ikChain.setIKDepth(rucursiveDepth);
+            ikChain.setIKWeight(weight);
+
+            List<BoneInfo> chainList = ikChain.getChainedBoneList();
+
+            for(Element orderElem : eachChild(ikChainElem, "chainOrder")){
+                String boneIdRef = getStringAttr(orderElem, "boneIdRef");
+                BoneInfo chaindBone = this.boneMap.get(boneIdRef);
+                chainList.add(chaindBone);
+            }
+        }
+
+        return;
+    }
+
+    private void buildMorphList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element morphListElem =
+                getChild(pmdModelElem, "morphList");
+
+        Map<MorphType, List<MorphPart>> morphMap = this.model.getMorphMap();
+
+        for(Element morphElem : eachChild(morphListElem, "morph")){
+            MorphPart morphPart = new MorphPart();
+
+            I18nText name = morphPart.getMorphName();
+            buildI18nName(morphElem, name);
+
+            String type = getStringAttr(morphElem, "type");
+            MorphType morphType = MorphType.valueOf(type);
+            morphPart.setMorphType(morphType);
+
+            List<MorphVertex> morphVertexList =
+                    morphPart.getMorphVertexList();
+
+            for(Element morphVertexElem
+                    : eachChild(morphElem, "morphVertex")){
+                String vtxIdRef = getStringAttr(morphVertexElem, "vtxIdRef");
+                Vertex baseVertex = this.vertexMap.get(vtxIdRef);
+                float xOff = getFloatAttr(morphVertexElem, "xOff");
+                float yOff = getFloatAttr(morphVertexElem, "yOff");
+                float zOff = getFloatAttr(morphVertexElem, "zOff");
+
+                MorphVertex morphVertex = new MorphVertex();
+                morphVertex.setBaseVertex(baseVertex);
+                Pos3d position = morphVertex.getOffset();
+                position.setXPos(xOff);
+                position.setYPos(yOff);
+                position.setZPos(zOff);
+
+                morphVertexList.add(morphVertex);
+            }
+
+            morphMap.get(morphType).add(morphPart);
+        }
+
+        List<MorphPart> serialList = new LinkedList<MorphPart>();
+        MorphPart baseDummy = new MorphPart();
+        serialList.add(baseDummy);
+        for(MorphPart part : morphMap.get(MorphType.EYEBROW)){
+            serialList.add(part);
+        }
+        for(MorphPart part : morphMap.get(MorphType.EYE)){
+            serialList.add(part);
+        }
+        for(MorphPart part : morphMap.get(MorphType.LIP)){
+            serialList.add(part);
+        }
+        for(MorphPart part : morphMap.get(MorphType.EXTRA)){
+            serialList.add(part);
+        }
+        ListUtil.assignIndexedSerial(serialList);
+
+        return;
+    }
+
+    private void buildBoneGroupList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element boneGroupListElem =
+                getChild(pmdModelElem, "boneGroupList");
+
+        List<BoneGroup> boneGroupList = this.model.getBoneGroupList();
+        BoneGroup defaultGroup = new BoneGroup();
+        boneGroupList.add(defaultGroup);
+
+        for(Element boneGroupElem
+                : eachChild(boneGroupListElem, "boneGroup")){
+            BoneGroup group = new BoneGroup();
+            boneGroupList.add(group);
+
+            I18nText name = group.getGroupName();
+            buildI18nName(boneGroupElem, name);
+
+            for(Element boneGroupMemberElem
+                    : eachChild(boneGroupElem, "boneGroupMember")){
+                String boneIdRef =
+                        getStringAttr(boneGroupMemberElem, "boneIdRef");
+                BoneInfo bone = this.boneMap.get(boneIdRef);
+                group.getBoneList().add(bone);
+            }
+        }
+
+        ListUtil.assignIndexedSerial(boneGroupList);
+
+        return;
+    }
+
+    private void buildRigidList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element rigidListElem =
+                getChild(pmdModelElem, "rigidList");
+
+        List<RigidInfo> rigidList = this.model.getRigidList();
+
+        for(Element rigidElem : eachChild(rigidListElem, "rigid")){
+            RigidInfo rigid = new RigidInfo();
+            rigidList.add(rigid);
+
+            I18nText name = rigid.getRigidName();
+            buildI18nName(rigidElem, name);
+
+            String behavior = getStringAttr(rigidElem, "behavior");
+            RigidBehaviorType type = RigidBehaviorType.valueOf(behavior);
+            rigid.setBehaviorType(type);
+
+            String rigidId = getStringAttr(rigidElem, "rigidId");
+            this.rigidMap.put(rigidId, rigid);
+
+            if(hasChild(rigidElem, "linkedBone")){
+                Element linkedBoneElem = getChild(rigidElem, "linkedBone");
+                String boneIdRef = getStringAttr(linkedBoneElem, "boneIdRef");
+                BoneInfo linkedBone = this.boneMap.get(boneIdRef);
+                rigid.setLinkedBone(linkedBone);
+            }
+
+            RigidShape rigidShape = rigid.getRigidShape();
+            if(hasChild(rigidElem, "rigidShapeSphere")){
+                Element shapeElem =
+                        getChild(rigidElem, "rigidShapeSphere");
+                float radius = getFloatAttr(shapeElem, "radius");
+                rigidShape.setShapeType(RigidShapeType.SPHERE);
+                rigidShape.setRadius(radius);
+            }
+            if(hasChild(rigidElem, "rigidShapeBox")){
+                Element shapeElem =
+                        getChild(rigidElem, "rigidShapeBox");
+                float width  = getFloatAttr(shapeElem, "width");
+                float height = getFloatAttr(shapeElem, "height");
+                float depth  = getFloatAttr(shapeElem, "depth");
+                rigidShape.setShapeType(RigidShapeType.BOX);
+                rigidShape.setWidth(width);
+                rigidShape.setHeight(height);
+                rigidShape.setDepth(depth);
+            }
+            if(hasChild(rigidElem, "rigidShapeCapsule")){
+                Element shapeElem =
+                        getChild(rigidElem, "rigidShapeCapsule");
+                float height = getFloatAttr(shapeElem, "height");
+                float radius = getFloatAttr(shapeElem, "radius");
+                rigidShape.setShapeType(RigidShapeType.CAPSULE);
+                rigidShape.setHeight(height);
+                rigidShape.setRadius(radius);
+            }
+
+            float xVal;
+            float yVal;
+            float zVal;
+
+            Element positionElem = getChild(rigidElem, "position");
+            xVal = getFloatAttr(positionElem, "x");
+            yVal = getFloatAttr(positionElem, "y");
+            zVal = getFloatAttr(positionElem, "z");
+            Pos3d position = rigid.getPosition();
+            position.setXPos(xVal);
+            position.setYPos(yVal);
+            position.setZPos(zVal);
+
+            Element radRotationElem = getChild(rigidElem, "radRotation");
+            xVal = getFloatAttr(radRotationElem, "xRad");
+            yVal = getFloatAttr(radRotationElem, "yRad");
+            zVal = getFloatAttr(radRotationElem, "zRad");
+            Rad3d rotation = rigid.getRotation();
+            rotation.setXRad(xVal);
+            rotation.setYRad(yVal);
+            rotation.setZRad(zVal);
+
+            Element dynamicsElem = getChild(rigidElem, "dynamics");
+            float mass = getFloatAttr(dynamicsElem, "mass");
+            float dampingPosition =
+                    getFloatAttr(dynamicsElem, "dampingPosition");
+            float dampingRotation =
+                    getFloatAttr(dynamicsElem, "dampingRotation");
+            float restitution = getFloatAttr(dynamicsElem, "restitution");
+            float friction = getFloatAttr(dynamicsElem, "friction");
+            DynamicsInfo dynamics = rigid.getDynamicsInfo();
+            dynamics.setMass(mass);
+            dynamics.setDampingPosition(dampingPosition);
+            dynamics.setDampingRotation(dampingRotation);
+            dynamics.setRestitution(restitution);
+            dynamics.setFriction(friction);
+        }
+
+        ListUtil.assignIndexedSerial(rigidList);
+
+        return;
+    }
+
+    private void buildRigidGroupList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element rigidGroupListElem =
+                getChild(pmdModelElem, "rigidGroupList");
+
+        List<RigidGroup> groupList = this.model.getRigidGroupList();
+
+        for(Element rigidGroupElem
+                : eachChild(rigidGroupListElem, "rigidGroup")){
+            RigidGroup rigidGroup = new RigidGroup();
+            groupList.add(rigidGroup);
+
+            String rigidGroupId =
+                    getStringAttr(rigidGroupElem, "rigidGroupId");
+            this.rigidGroupMap.put(rigidGroupId, rigidGroup);
+
+            for(Element memberElem
+                    : eachChild(rigidGroupElem, "rigidGroupMember")){
+                String rigidIdRef = getStringAttr(memberElem, "rigidIdRef");
+                RigidInfo rigid = this.rigidMap.get(rigidIdRef);
+                rigidGroup.getRigidList().add(rigid);
+                rigid.setRigidGroup(rigidGroup);
+            }
+        }
+
+        while(groupList.size() < 16){
+            RigidGroup rigidGroup = new RigidGroup();
+            groupList.add(rigidGroup);
+        }
+
+        ListUtil.assignIndexedSerial(groupList);
+
+        return;
+    }
+
+    private void resolveThroughRigidGroup(Element pmdModelElem)
+            throws TogaXmlException{
+        Element rigidListElem =
+                getChild(pmdModelElem, "rigidList");
+
+        List<RigidInfo> rigidList = this.model.getRigidList();
+
+        int serialNum = 0;
+        for(Element rigidElem : eachChild(rigidListElem, "rigid")){
+            RigidInfo rigid = rigidList.get(serialNum++);
+            for(Element groupElem
+                    : eachChild(rigidElem, "throughRigidGroup")){
+                String groupId = getStringAttr(groupElem, "rigidGroupIdRef");
+                RigidGroup group = this.rigidGroupMap.get(groupId);
+                rigid.getThroughGroupColl().add(group);
+            }
+        }
+
+        return;
+    }
+
+    private void buildJointList(Element pmdModelElem)
+            throws TogaXmlException{
+        Element jointListElem =
+                getChild(pmdModelElem, "jointList");
+
+        List<JointInfo> jointList = this.model.getJointList();
+
+        for(Element jointElem : eachChild(jointListElem, "joint")){
+            JointInfo joint = new JointInfo();
+            jointList.add(joint);
+
+            I18nText name = joint.getJointName();
+            buildI18nName(jointElem, name);
+
+            Element rigidPairElem = getChild(jointElem, "jointedRigidPair");
+            String rigidIdRef1 = getStringAttr(rigidPairElem, "rigidIdRef1");
+            String rigidIdRef2 = getStringAttr(rigidPairElem, "rigidIdRef2");
+            RigidInfo rigid1 = this.rigidMap.get(rigidIdRef1);
+            RigidInfo rigid2 = this.rigidMap.get(rigidIdRef2);
+            joint.setRigidPair(rigid1, rigid2);
+
+            float xVal;
+            float yVal;
+            float zVal;
+            float xFrom;
+            float xTo;
+            float yFrom;
+            float yTo;
+            float zFrom;
+            float zTo;
+
+            Pos3d position = joint.getPosition();
+            Element positionElem = getChild(jointElem, "position");
+            xVal = getFloatAttr(positionElem, "x");
+            yVal = getFloatAttr(positionElem, "y");
+            zVal = getFloatAttr(positionElem, "z");
+            position.setXPos(xVal);
+            position.setYPos(yVal);
+            position.setZPos(zVal);
+
+            TripletRange limitPosition = joint.getPositionRange();
+            Element limitPositionElem = getChild(jointElem, "limitPosition");
+            xFrom = getFloatAttr(limitPositionElem, "xFrom");
+            xTo   = getFloatAttr(limitPositionElem, "xTo");
+            yFrom = getFloatAttr(limitPositionElem, "yFrom");
+            yTo   = getFloatAttr(limitPositionElem, "yTo");
+            zFrom = getFloatAttr(limitPositionElem, "zFrom");
+            zTo   = getFloatAttr(limitPositionElem, "zTo");
+            limitPosition.setXRange(xFrom, xTo);
+            limitPosition.setYRange(yFrom, yTo);
+            limitPosition.setZRange(zFrom, zTo);
+
+            Rad3d rotation = joint.getRotation();
+            Element rotationElem = getChild(jointElem, "radRotation");
+            xVal = getFloatAttr(rotationElem, "xRad");
+            yVal = getFloatAttr(rotationElem, "yRad");
+            zVal = getFloatAttr(rotationElem, "zRad");
+            rotation.setXRad(xVal);
+            rotation.setYRad(yVal);
+            rotation.setZRad(zVal);
+
+            TripletRange limitRotation = joint.getRotationRange();
+            Element limitRotationElem = getChild(jointElem, "limitRotation");
+            xFrom = getFloatAttr(limitRotationElem, "xFrom");
+            xTo   = getFloatAttr(limitRotationElem, "xTo");
+            yFrom = getFloatAttr(limitRotationElem, "yFrom");
+            yTo   = getFloatAttr(limitRotationElem, "yTo");
+            zFrom = getFloatAttr(limitRotationElem, "zFrom");
+            zTo   = getFloatAttr(limitRotationElem, "zTo");
+            limitRotation.setXRange(xFrom, xTo);
+            limitRotation.setYRange(yFrom, yTo);
+            limitRotation.setZRange(zFrom, zTo);
+
+            Pos3d elasticPosition = joint.getElasticPosition();
+            Element elasticPositionElem =
+                    getChild(jointElem, "elasticPosition");
+            xVal = getFloatAttr(elasticPositionElem, "x");
+            yVal = getFloatAttr(elasticPositionElem, "y");
+            zVal = getFloatAttr(elasticPositionElem, "z");
+            elasticPosition.setXPos(xVal);
+            elasticPosition.setYPos(yVal);
+            elasticPosition.setZPos(zVal);
+
+            Deg3d elasticRotation = joint.getElasticRotation();
+            Element elasticRotationElem =
+                    getChild(jointElem, "elasticRotation");
+            xVal = getFloatAttr(elasticRotationElem, "xDeg");
+            yVal = getFloatAttr(elasticRotationElem, "yDeg");
+            zVal = getFloatAttr(elasticRotationElem, "zDeg");
+            elasticRotation.setXDeg(xVal);
+            elasticRotation.setYDeg(yVal);
+            elasticRotation.setZDeg(zVal);
+        }
+
+        return;
+    }
+
+}
index 649cfd0..ad60671 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * PMDモデル内容をXMLで出力するためのライブラリ。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd.xml;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * PMDモデル内容をXMLで出力するためのライブラリ。
+ */
+
+package jp.sourceforge.mikutoga.pmd.xml;
+
+/* EOF */
index eaad199..4b31cc6 100644 (file)
-/*\r
- * basic xml exporter\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\r
-\r
-import java.io.BufferedWriter;\r
-import java.io.Closeable;\r
-import java.io.Flushable;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.io.OutputStreamWriter;\r
-import java.nio.charset.Charset;\r
-import javax.xml.bind.DatatypeConverter;\r
-\r
-/**\r
- * 各種XMLエクスポータの基本機能。\r
- * UCS4は未サポート。\r
- */\r
-public class BasicXmlExporter {\r
-\r
-    /** デフォルトエンコーディング。 */\r
-    private static final Charset CS_UTF8 = Charset.forName("UTF-8");\r
-\r
-    /** デフォルトの改行文字列。 */\r
-    private static final String LF = "\n";       // 0x0a\r
-    /** デフォルトのインデント単位。 */\r
-    private static final String DEFAULT_INDENT_UNIT = "\u0020\u0020";\r
-\r
-    private static final char[] HEXCHAR_TABLE = {\r
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\r
-        'A', 'B', 'C', 'D', 'E', 'F',\r
-    };\r
-\r
-    static{\r
-        assert HEXCHAR_TABLE.length == 16;\r
-    }\r
-\r
-\r
-    private final Appendable appendable;\r
-\r
-    private String newline = LF;\r
-    private String indentUnit = DEFAULT_INDENT_UNIT;\r
-\r
-    private int indentNest = 0;\r
-    private boolean basicLatinOnlyOut = true;\r
-\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * 文字エンコーディングはUTF-8が用いられる。\r
-     * @param stream 出力ストリーム\r
-     */\r
-    public BasicXmlExporter(OutputStream stream){\r
-        this(stream, CS_UTF8);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param stream 出力ストリーム\r
-     * @param charSet 文字エンコーディング指定\r
-     */\r
-    public BasicXmlExporter(OutputStream stream, Charset charSet){\r
-        this(\r
-            new BufferedWriter(\r
-                new OutputStreamWriter(stream, charSet)\r
-            )\r
-        );\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param appendable 文字列出力\r
-     */\r
-    public BasicXmlExporter(Appendable appendable){\r
-        super();\r
-        this.appendable = appendable;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。\r
-     * @param ch 判定対象文字\r
-     * @return Basic-Latin文字ならtrue\r
-     */\r
-    public static boolean isBasicLatin(char ch){\r
-        if(ch <= 0x7f) return true;\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * 改行文字列を設定する。\r
-     * @param newLine 改行文字列\r
-     * @throws NullPointerException 引数がnull\r
-     */\r
-    public void setNewLine(String newLine) throws NullPointerException{\r
-        if(newLine == null) throw new NullPointerException();\r
-        this.newline = newLine;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * BasicLatin文字だけで出力するか設定する。\r
-     * BasicLatin以外の文字(≒日本語)をそのまま出力するか\r
-     * 文字参照で出力するかの設定が可能。\r
-     * コメント部中身は対象外。\r
-     * @param bool BasicLatin文字だけで出力するならtrue\r
-     */\r
-    public void setBasicLatinOnlyOut(boolean bool){\r
-        this.basicLatinOnlyOut = bool;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * BasicLatin文字だけを出力する状態か判定する。\r
-     * コメント部中身は対象外。\r
-     * @return BasicLatin文字だけで出力するならtrue\r
-     */\r
-    public boolean isBasicLatinOnlyOut(){\r
-        return this.basicLatinOnlyOut;\r
-    }\r
-\r
-    /**\r
-     * 改行文字列を設定する。\r
-     * デフォルトではLF(0x0a)\nが用いられる。\r
-     * @param seq 改行文字列。nullは空文字列""と解釈される。\r
-     */\r
-    public void setNewLine(CharSequence seq){\r
-        if(seq == null) this.newline = "";\r
-        else            this.newline = seq.toString();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * インデント単位文字列を設定する。\r
-     * デフォルトでは空白2個。\r
-     * @param seq インデント単位文字列。nullは空文字列""と解釈される。\r
-     */\r
-    public void setIndentUnit(CharSequence seq){\r
-        if(seq == null) this.indentUnit = "";\r
-        else            this.indentUnit = seq.toString();\r
-    }\r
-\r
-    /**\r
-     * 可能であれば出力をフラッシュする。\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public void flush() throws IOException{\r
-        if(this.appendable instanceof Flushable){\r
-            ((Flushable)this.appendable).flush();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 可能であれば出力をクローズする。\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public void close() throws IOException{\r
-        if(this.appendable instanceof Closeable){\r
-            ((Closeable)this.appendable).close();\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 1文字出力する。\r
-     * @param ch 文字\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter put(char ch) throws IOException{\r
-        this.appendable.append(ch);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 文字列を出力する。\r
-     * @param seq 文字列\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter put(CharSequence seq) throws IOException{\r
-        this.appendable.append(seq);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * int値を出力する。\r
-     * @param iVal int値\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     * @see java.lang.Integer#toString(int)\r
-     */\r
-    public BasicXmlExporter put(int iVal) throws IOException{\r
-        String value = DatatypeConverter.printInt(iVal);\r
-        this.appendable.append(value);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * float値を出力する。\r
-     * @param fVal float値\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     * @see java.lang.Float#toString(float)\r
-     */\r
-    public BasicXmlExporter put(float fVal) throws IOException{\r
-        String value = DatatypeConverter.printFloat(fVal);\r
-        this.appendable.append(value);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 改行を出力する。\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter ln() throws IOException{\r
-        this.appendable.append(this.newline);\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 改行を指定回数出力する。\r
-     * @param count 改行回数。0以下の場合は何も出力しない。\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter ln(int count) throws IOException{\r
-        for(int ct = 1; ct <= count; ct++){\r
-            this.appendable.append(this.newline);\r
-        }\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * インデントを出力する。\r
-     * インデント単位文字列をネストレベル回数分出力する。\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter ind() throws IOException{\r
-        for(int ct = 1; ct <= this.indentNest; ct++){\r
-            put(this.indentUnit);\r
-        }\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * インデントレベルを一段下げる。\r
-     */\r
-    public void pushNest(){\r
-        this.indentNest++;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * インデントレベルを一段上げる。\r
-     * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。\r
-     */\r
-    public void popNest(){\r
-        this.indentNest--;\r
-        if(this.indentNest < 0) this.indentNest = 0;\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定された文字を16進2桁の文字参照形式で出力する。\r
-     * 2桁で出力できない場合は4桁で出力する。\r
-     * @param ch 文字\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putCharRef2Hex(char ch) throws IOException{\r
-        if(ch > 0xff) return putCharRef4Hex(ch);\r
-\r
-        char hex3 = HEXCHAR_TABLE[(ch >> 4) & 0x000f];\r
-        char hex4 = HEXCHAR_TABLE[(ch     ) & 0x000f];\r
-\r
-        this.appendable.append("&#x");\r
-        this.appendable.append(hex3);\r
-        this.appendable.append(hex4);\r
-        this.appendable.append(';');\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 指定された文字を16進4桁の文字参照形式で出力する。\r
-     * UCS4に伴うサロゲートペアは未サポート\r
-     * @param ch 文字\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putCharRef4Hex(char ch) throws IOException{\r
-        char hex1 = HEXCHAR_TABLE[(ch >> 12) & 0x000f];\r
-        char hex2 = HEXCHAR_TABLE[(ch >>  8) & 0x000f];\r
-        char hex3 = HEXCHAR_TABLE[(ch >>  4) & 0x000f];\r
-        char hex4 = HEXCHAR_TABLE[(ch      ) & 0x000f];\r
-\r
-        this.appendable.append("&#x");\r
-        this.appendable.append(hex1);\r
-        this.appendable.append(hex2);\r
-        this.appendable.append(hex3);\r
-        this.appendable.append(hex4);\r
-        this.appendable.append(';');\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 要素の中身および属性値中身を出力する。\r
-     * 必要に応じてXML定義済み実体文字が割り振られた文字、\r
-     * コントロールコード、および非BasicLatin文字がエスケープされる。\r
-     * @param content 内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putContent(CharSequence content)\r
-            throws IOException{\r
-        int length = content.length();\r
-\r
-        for(int pos = 0; pos < length; pos++){\r
-            char ch = content.charAt(pos);\r
-            if(Character.isISOControl(ch)){\r
-                putCharRef2Hex(ch);\r
-            }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){\r
-                putCharRef4Hex(ch);\r
-            }else{\r
-                switch(ch){\r
-                case '&':  this.appendable.append("&amp;");  break;\r
-                case '<':  this.appendable.append("&lt;");   break;\r
-                case '>':  this.appendable.append("&gt;");   break;\r
-                case '"':  this.appendable.append("&quot;"); break;\r
-                case '\'': this.appendable.append("&apos;"); break;\r
-                case '\u00a5': this.appendable.append('\u005c\u005c'); break;\r
-                default:   this.appendable.append(ch);       break;\r
-                }\r
-            }\r
-        }\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 属性値を出力する。\r
-     * @param attrName 属性名\r
-     * @param content 属性内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putAttr(CharSequence attrName,\r
-                                     CharSequence content)\r
-            throws IOException{\r
-        put(attrName).put('=').put('"').putContent(content).put('"');\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * int型属性値を出力する。\r
-     * @param attrName 属性名\r
-     * @param iVal int値\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putIntAttr(CharSequence attrName,\r
-                                           int iVal)\r
-            throws IOException{\r
-        put(attrName).put('=').put('"').put(iVal).put('"');\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * float型属性値を出力する。\r
-     * @param attrName 属性名\r
-     * @param fVal float値\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putFloatAttr(CharSequence attrName,\r
-                                              float fVal)\r
-            throws IOException{\r
-        put(attrName).put('=').put('"').put(fVal).put('"');\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * コメントの内容を出力する。\r
-     * コメント中の\n記号出現に伴い、\r
-     * あらかじめ指定された改行文字が出力される。\r
-     * \n以外のコントロールコード各種、\r
-     * 及び非BasicLatin文字はそのまま出力される。\r
-     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。\r
-     * @param comment コメント内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putCommentContent(CharSequence comment)\r
-            throws IOException{\r
-        int length = comment.length();\r
-\r
-        char prev = '\0';\r
-        for(int pos = 0; pos < length; pos++){\r
-            char ch = comment.charAt(pos);\r
-            if(ch == '\n'){\r
-                ln();\r
-                prev = ch;\r
-                continue;\r
-            }\r
-            if(prev == '-' && ch == '-') put(' ');\r
-            put(ch);\r
-            prev = ch;\r
-        }\r
-\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * 1行コメントを出力する。\r
-     * コメント中の\n記号出現に伴い、\r
-     * あらかじめ指定された改行文字が出力される。\r
-     * \n以外のコントロールコード各種、\r
-     * 及び非BasicLatin文字はそのまま出力される。\r
-     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。\r
-     * @param comment コメント内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putLineComment(CharSequence comment)\r
-            throws IOException{\r
-        put("<!--").put(' ');\r
-        putCommentContent(comment);\r
-        put(' ').put("-->");\r
-        return this;\r
-    }\r
-\r
-    /**\r
-     * ブロックコメントを出力する。\r
-     * コメント中の\n記号出現に伴い、\r
-     * あらかじめ指定された改行文字が出力される。\r
-     * \n以外のコントロールコード各種、\r
-     * 及び非BasicLatin文字はそのまま出力される。\r
-     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。\r
-     * @param comment コメント内容\r
-     * @return this本体\r
-     * @throws IOException 出力エラー\r
-     */\r
-    public BasicXmlExporter putBlockComment(CharSequence comment)\r
-            throws IOException{\r
-        put("<!--").ln();\r
-\r
-        putCommentContent(comment);\r
-\r
-        int commentLength = comment.length();\r
-        if(commentLength > 0){\r
-            char lastCh = comment.charAt(commentLength - 1);\r
-            if(lastCh != '\n') ln();\r
-        }\r
-\r
-        put("-->").ln();\r
-\r
-        return this;\r
-    }\r
-\r
-}\r
+/*
+ * basic xml exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.BufferedWriter;
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import javax.xml.bind.DatatypeConverter;
+
+/**
+ * 各種XMLエクスポータの基本機能。
+ * UCS4は未サポート。
+ */
+public class BasicXmlExporter {
+
+    /** デフォルトエンコーディング。 */
+    private static final Charset CS_UTF8 = Charset.forName("UTF-8");
+
+    /** デフォルトの改行文字列。 */
+    private static final String LF = "\n";       // 0x0a
+    /** デフォルトのインデント単位。 */
+    private static final String DEFAULT_INDENT_UNIT = "\u0020\u0020";
+
+    private static final char[] HEXCHAR_TABLE = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'A', 'B', 'C', 'D', 'E', 'F',
+    };
+
+    static{
+        assert HEXCHAR_TABLE.length == 16;
+    }
+
+
+    private final Appendable appendable;
+
+    private String newline = LF;
+    private String indentUnit = DEFAULT_INDENT_UNIT;
+
+    private int indentNest = 0;
+    private boolean basicLatinOnlyOut = true;
+
+
+    /**
+     * コンストラクタ。
+     * 文字エンコーディングはUTF-8が用いられる。
+     * @param stream 出力ストリーム
+     */
+    public BasicXmlExporter(OutputStream stream){
+        this(stream, CS_UTF8);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param stream 出力ストリーム
+     * @param charSet 文字エンコーディング指定
+     */
+    public BasicXmlExporter(OutputStream stream, Charset charSet){
+        this(
+            new BufferedWriter(
+                new OutputStreamWriter(stream, charSet)
+            )
+        );
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param appendable 文字列出力
+     */
+    public BasicXmlExporter(Appendable appendable){
+        super();
+        this.appendable = appendable;
+        return;
+    }
+
+    /**
+     * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。
+     * @param ch 判定対象文字
+     * @return Basic-Latin文字ならtrue
+     */
+    public static boolean isBasicLatin(char ch){
+        if(ch <= 0x7f) return true;
+        return false;
+    }
+
+    /**
+     * 改行文字列を設定する。
+     * @param newLine 改行文字列
+     * @throws NullPointerException 引数がnull
+     */
+    public void setNewLine(String newLine) throws NullPointerException{
+        if(newLine == null) throw new NullPointerException();
+        this.newline = newLine;
+        return;
+    }
+
+    /**
+     * BasicLatin文字だけで出力するか設定する。
+     * BasicLatin以外の文字(≒日本語)をそのまま出力するか
+     * 文字参照で出力するかの設定が可能。
+     * コメント部中身は対象外。
+     * @param bool BasicLatin文字だけで出力するならtrue
+     */
+    public void setBasicLatinOnlyOut(boolean bool){
+        this.basicLatinOnlyOut = bool;
+        return;
+    }
+
+    /**
+     * BasicLatin文字だけを出力する状態か判定する。
+     * コメント部中身は対象外。
+     * @return BasicLatin文字だけで出力するならtrue
+     */
+    public boolean isBasicLatinOnlyOut(){
+        return this.basicLatinOnlyOut;
+    }
+
+    /**
+     * 改行文字列を設定する。
+     * デフォルトではLF(0x0a)\nが用いられる。
+     * @param seq 改行文字列。nullは空文字列""と解釈される。
+     */
+    public void setNewLine(CharSequence seq){
+        if(seq == null) this.newline = "";
+        else            this.newline = seq.toString();
+        return;
+    }
+
+    /**
+     * インデント単位文字列を設定する。
+     * デフォルトでは空白2個。
+     * @param seq インデント単位文字列。nullは空文字列""と解釈される。
+     */
+    public void setIndentUnit(CharSequence seq){
+        if(seq == null) this.indentUnit = "";
+        else            this.indentUnit = seq.toString();
+    }
+
+    /**
+     * 可能であれば出力をフラッシュする。
+     * @throws IOException 出力エラー
+     */
+    public void flush() throws IOException{
+        if(this.appendable instanceof Flushable){
+            ((Flushable)this.appendable).flush();
+        }
+        return;
+    }
+
+    /**
+     * 可能であれば出力をクローズする。
+     * @throws IOException 出力エラー
+     */
+    public void close() throws IOException{
+        if(this.appendable instanceof Closeable){
+            ((Closeable)this.appendable).close();
+        }
+        return;
+    }
+
+    /**
+     * 1文字出力する。
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter put(char ch) throws IOException{
+        this.appendable.append(ch);
+        return this;
+    }
+
+    /**
+     * 文字列を出力する。
+     * @param seq 文字列
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter put(CharSequence seq) throws IOException{
+        this.appendable.append(seq);
+        return this;
+    }
+
+    /**
+     * int値を出力する。
+     * @param iVal int値
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see java.lang.Integer#toString(int)
+     */
+    public BasicXmlExporter put(int iVal) throws IOException{
+        String value = DatatypeConverter.printInt(iVal);
+        this.appendable.append(value);
+        return this;
+    }
+
+    /**
+     * float値を出力する。
+     * @param fVal float値
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see java.lang.Float#toString(float)
+     */
+    public BasicXmlExporter put(float fVal) throws IOException{
+        String value = DatatypeConverter.printFloat(fVal);
+        this.appendable.append(value);
+        return this;
+    }
+
+    /**
+     * 改行を出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter ln() throws IOException{
+        this.appendable.append(this.newline);
+        return this;
+    }
+
+    /**
+     * 改行を指定回数出力する。
+     * @param count 改行回数。0以下の場合は何も出力しない。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter ln(int count) throws IOException{
+        for(int ct = 1; ct <= count; ct++){
+            this.appendable.append(this.newline);
+        }
+        return this;
+    }
+
+    /**
+     * インデントを出力する。
+     * インデント単位文字列をネストレベル回数分出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter ind() throws IOException{
+        for(int ct = 1; ct <= this.indentNest; ct++){
+            put(this.indentUnit);
+        }
+        return this;
+    }
+
+    /**
+     * インデントレベルを一段下げる。
+     */
+    public void pushNest(){
+        this.indentNest++;
+        return;
+    }
+
+    /**
+     * インデントレベルを一段上げる。
+     * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。
+     */
+    public void popNest(){
+        this.indentNest--;
+        if(this.indentNest < 0) this.indentNest = 0;
+        return;
+    }
+
+    /**
+     * 指定された文字を16進2桁の文字参照形式で出力する。
+     * 2桁で出力できない場合は4桁で出力する。
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putCharRef2Hex(char ch) throws IOException{
+        if(ch > 0xff) return putCharRef4Hex(ch);
+
+        char hex3 = HEXCHAR_TABLE[(ch >> 4) & 0x000f];
+        char hex4 = HEXCHAR_TABLE[(ch     ) & 0x000f];
+
+        this.appendable.append("&#x");
+        this.appendable.append(hex3);
+        this.appendable.append(hex4);
+        this.appendable.append(';');
+
+        return this;
+    }
+
+    /**
+     * 指定された文字を16進4桁の文字参照形式で出力する。
+     * UCS4に伴うサロゲートペアは未サポート
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putCharRef4Hex(char ch) throws IOException{
+        char hex1 = HEXCHAR_TABLE[(ch >> 12) & 0x000f];
+        char hex2 = HEXCHAR_TABLE[(ch >>  8) & 0x000f];
+        char hex3 = HEXCHAR_TABLE[(ch >>  4) & 0x000f];
+        char hex4 = HEXCHAR_TABLE[(ch      ) & 0x000f];
+
+        this.appendable.append("&#x");
+        this.appendable.append(hex1);
+        this.appendable.append(hex2);
+        this.appendable.append(hex3);
+        this.appendable.append(hex4);
+        this.appendable.append(';');
+
+        return this;
+    }
+
+    /**
+     * 要素の中身および属性値中身を出力する。
+     * 必要に応じてXML定義済み実体文字が割り振られた文字、
+     * コントロールコード、および非BasicLatin文字がエスケープされる。
+     * @param content 内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putContent(CharSequence content)
+            throws IOException{
+        int length = content.length();
+
+        for(int pos = 0; pos < length; pos++){
+            char ch = content.charAt(pos);
+            if(Character.isISOControl(ch)){
+                putCharRef2Hex(ch);
+            }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){
+                putCharRef4Hex(ch);
+            }else{
+                switch(ch){
+                case '&':  this.appendable.append("&amp;");  break;
+                case '<':  this.appendable.append("&lt;");   break;
+                case '>':  this.appendable.append("&gt;");   break;
+                case '"':  this.appendable.append("&quot;"); break;
+                case '\'': this.appendable.append("&apos;"); break;
+                case '\u00a5': this.appendable.append('\u005c\u005c'); break;
+                default:   this.appendable.append(ch);       break;
+                }
+            }
+        }
+
+        return this;
+    }
+
+    /**
+     * 属性値を出力する。
+     * @param attrName 属性名
+     * @param content 属性内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putAttr(CharSequence attrName,
+                                     CharSequence content)
+            throws IOException{
+        put(attrName).put('=').put('"').putContent(content).put('"');
+        return this;
+    }
+
+    /**
+     * int型属性値を出力する。
+     * @param attrName 属性名
+     * @param iVal int値
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putIntAttr(CharSequence attrName,
+                                           int iVal)
+            throws IOException{
+        put(attrName).put('=').put('"').put(iVal).put('"');
+        return this;
+    }
+
+    /**
+     * float型属性値を出力する。
+     * @param attrName 属性名
+     * @param fVal float値
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putFloatAttr(CharSequence attrName,
+                                              float fVal)
+            throws IOException{
+        put(attrName).put('=').put('"').put(fVal).put('"');
+        return this;
+    }
+
+    /**
+     * コメントの内容を出力する。
+     * コメント中の\n記号出現に伴い、
+     * あらかじめ指定された改行文字が出力される。
+     * \n以外のコントロールコード各種、
+     * 及び非BasicLatin文字はそのまま出力される。
+     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putCommentContent(CharSequence comment)
+            throws IOException{
+        int length = comment.length();
+
+        char prev = '\0';
+        for(int pos = 0; pos < length; pos++){
+            char ch = comment.charAt(pos);
+            if(ch == '\n'){
+                ln();
+                prev = ch;
+                continue;
+            }
+            if(prev == '-' && ch == '-') put(' ');
+            put(ch);
+            prev = ch;
+        }
+
+        return this;
+    }
+
+    /**
+     * 1行コメントを出力する。
+     * コメント中の\n記号出現に伴い、
+     * あらかじめ指定された改行文字が出力される。
+     * \n以外のコントロールコード各種、
+     * 及び非BasicLatin文字はそのまま出力される。
+     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putLineComment(CharSequence comment)
+            throws IOException{
+        put("<!--").put(' ');
+        putCommentContent(comment);
+        put(' ').put("-->");
+        return this;
+    }
+
+    /**
+     * ブロックコメントを出力する。
+     * コメント中の\n記号出現に伴い、
+     * あらかじめ指定された改行文字が出力される。
+     * \n以外のコントロールコード各種、
+     * 及び非BasicLatin文字はそのまま出力される。
+     * 連続するハイフン(-)記号間には強制的にスペースが挿入される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    public BasicXmlExporter putBlockComment(CharSequence comment)
+            throws IOException{
+        put("<!--").ln();
+
+        putCommentContent(comment);
+
+        int commentLength = comment.length();
+        if(commentLength > 0){
+            char lastCh = comment.charAt(commentLength - 1);
+            if(lastCh != '\n') ln();
+        }
+
+        put("-->").ln();
+
+        return this;
+    }
+
+}
index e1750b8..fcd88b9 100644 (file)
-/*\r
- * XML DOM utilities\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\r
-\r
-import java.util.Iterator;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.NoSuchElementException;\r
-import javax.xml.bind.DatatypeConverter;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.Node;\r
-\r
-/**\r
- * DOMユーティリティ。\r
- */\r
-public final class DomUtils {\r
-\r
-    /**\r
-     * 隠しコンストラクタ。\r
-     */\r
-    private DomUtils(){\r
-        super();\r
-        assert false;\r
-        throw new AssertionError();\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:string型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return 文字列\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    public static String getStringAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        if( ! elem.hasAttribute(attrName) ){\r
-            String message = "Attr:[" + attrName + "] "\r
-                    + "was not found in "\r
-                    + "Elem:[" + elem.getTagName()+"]";\r
-            throw new TogaXmlException(message);\r
-        }\r
-\r
-        String result;\r
-        try{\r
-            result = elem.getAttribute(attrName);\r
-        }catch(IllegalArgumentException e){\r
-            String message = "Invalid attribute form [" + attrName + "]";\r
-            throw new TogaXmlException(message, e);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:boolean型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return 真ならtrue\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    public static boolean getBooleanAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        String value = getStringAttr(elem, attrName);\r
-\r
-        boolean result;\r
-        try{\r
-            result = DatatypeConverter.parseBoolean(value);\r
-        }catch(IllegalArgumentException e){\r
-            String message =\r
-                    "Invalid boolean attribute form "\r
-                    + "[" + attrName + "][" + value + "]";\r
-            throw new TogaXmlException(message, e);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:integer型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return int値\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    public static int getIntegerAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        String value = getStringAttr(elem, attrName);\r
-\r
-        int result;\r
-        try{\r
-            result = DatatypeConverter.parseInt(value);\r
-        }catch(IllegalArgumentException e){\r
-            String message =\r
-                    "Invalid integer attribute form "\r
-                    + "[" + attrName + "][" + value + "]";\r
-            throw new TogaXmlException(message, e);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 要素からxsd:float型属性値を読み取る。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return float値\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    public static float getFloatAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        String value = getStringAttr(elem, attrName);\r
-\r
-        float result;\r
-        try{\r
-            result = DatatypeConverter.parseFloat(value);\r
-        }catch(IllegalArgumentException e){\r
-            String message =\r
-                    "Invalid float attribute form "\r
-                    + "[" + attrName + "][" + value + "]";\r
-            throw new TogaXmlException(message, e);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 要素から日本語Windows用ファイル名を属性値として読み取る。\r
-     * 念のため文字U+00A5は文字U-005Cに変換される。\r
-     * @param elem 要素\r
-     * @param attrName 属性名\r
-     * @return ファイル名\r
-     * @throws TogaXmlException 属性値が見つからなかった。\r
-     */\r
-    public static String getSjisFileNameAttr(Element elem, String attrName)\r
-            throws TogaXmlException{\r
-        String result;\r
-        try{\r
-            result = getStringAttr(elem, attrName);\r
-        }catch(IllegalArgumentException e){\r
-            String message =\r
-                    "Invalid winfile attribute form "\r
-                    + "[" + attrName + "]";\r
-            throw new TogaXmlException(message, e);\r
-        }\r
-\r
-        result.replace("" + '\u00a5', "" + '\u005c\u005c');\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素を1つだけ返す。\r
-     * @param parent 親要素\r
-     * @param tagName 子要素名\r
-     * @return 子要素\r
-     * @throws TogaXmlException 1つも見つからなかった\r
-     */\r
-    public static Element getChild(Element parent, String tagName)\r
-            throws TogaXmlException{\r
-        Element result = null;\r
-\r
-        for(Node node = parent.getFirstChild();\r
-            node != null;\r
-            node = node.getNextSibling() ){\r
-\r
-            if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
-            Element elem = (Element) node;\r
-\r
-            String elemTagName = elem.getTagName();\r
-            if( tagName.equals(elemTagName) ){\r
-                result = elem;\r
-                break;\r
-            }\r
-        }\r
-\r
-        if(result == null){\r
-            String message =\r
-                    "Elem:[" + tagName + "] was not found in "\r
-                    +"Elem:[" + parent.getTagName() + "]";\r
-            throw new TogaXmlException(message);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 親要素が指定された名前の子要素を持つか判定する。\r
-     * @param parent 親要素\r
-     * @param tagName 子要素名\r
-     * @return 指定名の子要素が存在すればtrue\r
-     */\r
-    public static boolean hasChild(Element parent, String tagName){\r
-        for(Node node = parent.getFirstChild();\r
-            node != null;\r
-            node = node.getNextSibling() ){\r
-\r
-            if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
-            Element elem = (Element) node;\r
-\r
-            String elemTagName = elem.getTagName();\r
-            if( tagName.equals(elemTagName) ) return true;\r
-        }\r
-\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素のリストを返す。\r
-     * @param parent 親要素\r
-     * @param childTag 子要素名\r
-     * @return 子要素のリスト\r
-     */\r
-    public static List<Element> getChildList(Element parent,\r
-                                               String childTag){\r
-        List<Element> result = new LinkedList<Element>();\r
-\r
-        for(Node node = parent.getFirstChild();\r
-            node != null;\r
-            node = node.getNextSibling() ){\r
-\r
-            if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
-            Element elem = (Element) node;\r
-\r
-            String tagName = elem.getTagName();\r
-            if( ! childTag.equals(tagName) ) continue;\r
-\r
-            result.add(elem);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素の列挙子を返す。\r
-     * @param parent 親要素\r
-     * @param childTag 子要素名\r
-     * @return 子要素の列挙子\r
-     */\r
-    public static Iterator<Element> getChildIterator(Element parent,\r
-                                                       String childTag){\r
-        Element firstElem;\r
-        try{\r
-            firstElem = getChild(parent, childTag);\r
-        }catch(TogaXmlException e){\r
-            firstElem = null;\r
-        }\r
-\r
-        Iterator<Element> result = new ElemIterator(firstElem);\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 指定された名前の子要素のforeachを返す。\r
-     * @param parent 親要素\r
-     * @param childTag 子要素名\r
-     * @return 子要素のforeach\r
-     */\r
-    public static Iterable<Element> getEachChild(Element parent,\r
-                                                   String childTag){\r
-        final Iterator<Element> iterator = getChildIterator(parent, childTag);\r
-        Iterable<Element> result = new Iterable<Element>(){\r
-            @Override\r
-            public Iterator<Element> iterator(){\r
-                return iterator;\r
-            }\r
-        };\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * 要素の次の要素を返す。\r
-     * @param elem 要素\r
-     * @return 次の要素。なければnull\r
-     */\r
-    public static Element nextElement(Element elem){\r
-        Node nextNode = elem;\r
-        for(;;){\r
-            nextNode = nextNode.getNextSibling();\r
-            if(nextNode == null) break;\r
-            if(nextNode.getNodeType() == Node.ELEMENT_NODE){\r
-                break;\r
-            }\r
-        }\r
-\r
-        return (Element) nextNode;\r
-    }\r
-\r
-    /**\r
-     * 同じ要素名を持つ次の要素を返す。\r
-     * @param elem 要素\r
-     * @return 次の要素。なければnull\r
-     */\r
-    public static Element nextNamedElement(Element elem){\r
-        String tagName = elem.getTagName();\r
-        Element nextElem = elem;\r
-        for(;;){\r
-            nextElem = nextElement(nextElem);\r
-            if(nextElem == null) break;\r
-            if(tagName.equals(nextElem.getTagName())) break;\r
-        }\r
-\r
-        return nextElem;\r
-    }\r
-\r
-    /**\r
-     * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。\r
-     */\r
-    private static class ElemIterator implements Iterator<Element>{\r
-        private Element next;\r
-\r
-        /**\r
-         * コンストラクタ。\r
-         * @param elem 最初の要素。nullを指定すれば空列挙子となる。\r
-         */\r
-        private ElemIterator(Element elem){\r
-            super();\r
-            this.next = elem;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public boolean hasNext(){\r
-            if(this.next == null) return false;\r
-            return true;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         * @throws NoSuchElementException {@inheritDoc}\r
-         */\r
-        @Override\r
-        public Element next() throws NoSuchElementException{\r
-            if(this.next == null) throw new NoSuchElementException();\r
-            Element result = this.next;\r
-            this.next = nextNamedElement(this.next);\r
-            return result;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * ※ 未サポート。\r
-         */\r
-        @Override\r
-        public void remove(){\r
-            throw new UnsupportedOperationException();\r
-        }\r
-\r
-    }\r
-\r
-}\r
+/*
+ * XML DOM utilities
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import javax.xml.bind.DatatypeConverter;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * DOMユーティリティ。
+ */
+public final class DomUtils {
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private DomUtils(){
+        super();
+        assert false;
+        throw new AssertionError();
+    }
+
+    /**
+     * 要素からxsd:string型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return 文字列
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    public static String getStringAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        if( ! elem.hasAttribute(attrName) ){
+            String message = "Attr:[" + attrName + "] "
+                    + "was not found in "
+                    + "Elem:[" + elem.getTagName()+"]";
+            throw new TogaXmlException(message);
+        }
+
+        String result;
+        try{
+            result = elem.getAttribute(attrName);
+        }catch(IllegalArgumentException e){
+            String message = "Invalid attribute form [" + attrName + "]";
+            throw new TogaXmlException(message, e);
+        }
+
+        return result;
+    }
+
+    /**
+     * 要素からxsd:boolean型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return 真ならtrue
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    public static boolean getBooleanAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        String value = getStringAttr(elem, attrName);
+
+        boolean result;
+        try{
+            result = DatatypeConverter.parseBoolean(value);
+        }catch(IllegalArgumentException e){
+            String message =
+                    "Invalid boolean attribute form "
+                    + "[" + attrName + "][" + value + "]";
+            throw new TogaXmlException(message, e);
+        }
+
+        return result;
+    }
+
+    /**
+     * 要素からxsd:integer型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return int値
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    public static int getIntegerAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        String value = getStringAttr(elem, attrName);
+
+        int result;
+        try{
+            result = DatatypeConverter.parseInt(value);
+        }catch(IllegalArgumentException e){
+            String message =
+                    "Invalid integer attribute form "
+                    + "[" + attrName + "][" + value + "]";
+            throw new TogaXmlException(message, e);
+        }
+
+        return result;
+    }
+
+    /**
+     * 要素からxsd:float型属性値を読み取る。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return float値
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    public static float getFloatAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        String value = getStringAttr(elem, attrName);
+
+        float result;
+        try{
+            result = DatatypeConverter.parseFloat(value);
+        }catch(IllegalArgumentException e){
+            String message =
+                    "Invalid float attribute form "
+                    + "[" + attrName + "][" + value + "]";
+            throw new TogaXmlException(message, e);
+        }
+
+        return result;
+    }
+
+    /**
+     * 要素から日本語Windows用ファイル名を属性値として読み取る。
+     * 念のため文字U+00A5は文字U-005Cに変換される。
+     * @param elem 要素
+     * @param attrName 属性名
+     * @return ファイル名
+     * @throws TogaXmlException 属性値が見つからなかった。
+     */
+    public static String getSjisFileNameAttr(Element elem, String attrName)
+            throws TogaXmlException{
+        String result;
+        try{
+            result = getStringAttr(elem, attrName);
+        }catch(IllegalArgumentException e){
+            String message =
+                    "Invalid winfile attribute form "
+                    + "[" + attrName + "]";
+            throw new TogaXmlException(message, e);
+        }
+
+        result.replace("" + '\u00a5', "" + '\u005c\u005c');
+
+        return result;
+    }
+
+    /**
+     * 指定された名前の子要素を1つだけ返す。
+     * @param parent 親要素
+     * @param tagName 子要素名
+     * @return 子要素
+     * @throws TogaXmlException 1つも見つからなかった
+     */
+    public static Element getChild(Element parent, String tagName)
+            throws TogaXmlException{
+        Element result = null;
+
+        for(Node node = parent.getFirstChild();
+            node != null;
+            node = node.getNextSibling() ){
+
+            if(node.getNodeType() != Node.ELEMENT_NODE) continue;
+            Element elem = (Element) node;
+
+            String elemTagName = elem.getTagName();
+            if( tagName.equals(elemTagName) ){
+                result = elem;
+                break;
+            }
+        }
+
+        if(result == null){
+            String message =
+                    "Elem:[" + tagName + "] was not found in "
+                    +"Elem:[" + parent.getTagName() + "]";
+            throw new TogaXmlException(message);
+        }
+
+        return result;
+    }
+
+    /**
+     * 親要素が指定された名前の子要素を持つか判定する。
+     * @param parent 親要素
+     * @param tagName 子要素名
+     * @return 指定名の子要素が存在すればtrue
+     */
+    public static boolean hasChild(Element parent, String tagName){
+        for(Node node = parent.getFirstChild();
+            node != null;
+            node = node.getNextSibling() ){
+
+            if(node.getNodeType() != Node.ELEMENT_NODE) continue;
+            Element elem = (Element) node;
+
+            String elemTagName = elem.getTagName();
+            if( tagName.equals(elemTagName) ) return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 指定された名前の子要素のリストを返す。
+     * @param parent 親要素
+     * @param childTag 子要素名
+     * @return 子要素のリスト
+     */
+    public static List<Element> getChildList(Element parent,
+                                               String childTag){
+        List<Element> result = new LinkedList<Element>();
+
+        for(Node node = parent.getFirstChild();
+            node != null;
+            node = node.getNextSibling() ){
+
+            if(node.getNodeType() != Node.ELEMENT_NODE) continue;
+            Element elem = (Element) node;
+
+            String tagName = elem.getTagName();
+            if( ! childTag.equals(tagName) ) continue;
+
+            result.add(elem);
+        }
+
+        return result;
+    }
+
+    /**
+     * 指定された名前の子要素の列挙子を返す。
+     * @param parent 親要素
+     * @param childTag 子要素名
+     * @return 子要素の列挙子
+     */
+    public static Iterator<Element> getChildIterator(Element parent,
+                                                       String childTag){
+        Element firstElem;
+        try{
+            firstElem = getChild(parent, childTag);
+        }catch(TogaXmlException e){
+            firstElem = null;
+        }
+
+        Iterator<Element> result = new ElemIterator(firstElem);
+
+        return result;
+    }
+
+    /**
+     * 指定された名前の子要素のforeachを返す。
+     * @param parent 親要素
+     * @param childTag 子要素名
+     * @return 子要素のforeach
+     */
+    public static Iterable<Element> getEachChild(Element parent,
+                                                   String childTag){
+        final Iterator<Element> iterator = getChildIterator(parent, childTag);
+        Iterable<Element> result = new Iterable<Element>(){
+            @Override
+            public Iterator<Element> iterator(){
+                return iterator;
+            }
+        };
+        return result;
+    }
+
+    /**
+     * 要素の次の要素を返す。
+     * @param elem 要素
+     * @return 次の要素。なければnull
+     */
+    public static Element nextElement(Element elem){
+        Node nextNode = elem;
+        for(;;){
+            nextNode = nextNode.getNextSibling();
+            if(nextNode == null) break;
+            if(nextNode.getNodeType() == Node.ELEMENT_NODE){
+                break;
+            }
+        }
+
+        return (Element) nextNode;
+    }
+
+    /**
+     * 同じ要素名を持つ次の要素を返す。
+     * @param elem 要素
+     * @return 次の要素。なければnull
+     */
+    public static Element nextNamedElement(Element elem){
+        String tagName = elem.getTagName();
+        Element nextElem = elem;
+        for(;;){
+            nextElem = nextElement(nextElem);
+            if(nextElem == null) break;
+            if(tagName.equals(nextElem.getTagName())) break;
+        }
+
+        return nextElem;
+    }
+
+    /**
+     * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。
+     */
+    private static class ElemIterator implements Iterator<Element>{
+        private Element next;
+
+        /**
+         * コンストラクタ。
+         * @param elem 最初の要素。nullを指定すれば空列挙子となる。
+         */
+        private ElemIterator(Element elem){
+            super();
+            this.next = elem;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public boolean hasNext(){
+            if(this.next == null) return false;
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         * @throws NoSuchElementException {@inheritDoc}
+         */
+        @Override
+        public Element next() throws NoSuchElementException{
+            if(this.next == null) throw new NoSuchElementException();
+            Element result = this.next;
+            this.next = nextNamedElement(this.next);
+            return result;
+        }
+
+        /**
+         * {@inheritDoc}
+         * ※ 未サポート。
+         */
+        @Override
+        public void remove(){
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+}
index 1a3a955..d25a25f 100644 (file)
@@ -1,52 +1,52 @@
-/*\r
- * exception about xml\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\r
-\r
-/**\r
- * 意図しないXML文書を検出した際の例外。\r
- */\r
-@SuppressWarnings("serial")\r
-public class TogaXmlException extends Exception{\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public TogaXmlException(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message メッセージ\r
-     */\r
-    public TogaXmlException(String message){\r
-        super(message);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param message メッセージ\r
-     * @param cause 原因の例外\r
-     */\r
-    public TogaXmlException(String message, Throwable cause){\r
-        super(message, cause);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * @param cause 原因の例外\r
-     */\r
-    public TogaXmlException(Throwable cause){\r
-        super(cause);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * exception about xml
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+/**
+ * 意図しないXML文書を検出した際の例外。
+ */
+@SuppressWarnings("serial")
+public class TogaXmlException extends Exception{
+
+    /**
+     * コンストラクタ。
+     */
+    public TogaXmlException(){
+        super();
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message メッセージ
+     */
+    public TogaXmlException(String message){
+        super(message);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param message メッセージ
+     * @param cause 原因の例外
+     */
+    public TogaXmlException(String message, Throwable cause){
+        super(message, cause);
+        return;
+    }
+
+    /**
+     * コンストラクタ。
+     * @param cause 原因の例外
+     */
+    public TogaXmlException(Throwable cause){
+        super(cause);
+        return;
+    }
+
+}
index 6723789..1bb3acf 100644 (file)
-/*\r
- * xml resource resolver\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2009 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.Reader;\r
-import java.net.URI;\r
-import java.net.URISyntaxException;\r
-import java.net.URL;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import org.w3c.dom.ls.LSInput;\r
-import org.w3c.dom.ls.LSResourceResolver;\r
-import org.xml.sax.EntityResolver;\r
-import org.xml.sax.InputSource;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。\r
- * 相対URIはこのクラスをベースに解決される。\r
- * 主な用途は外部スキーマのリソース化など。\r
- */\r
-public class XmlResourceResolver\r
-        implements LSResourceResolver, EntityResolver {\r
-\r
-    public static final String SCHEMA_XML =\r
-            "http://www.w3.org/2001/xml.xsd";\r
-    public static final String NS_XSD =\r
-            "http://www.w3.org/2001/XMLSchema-instance";\r
-\r
-    private static final String LOCAL_SCHEMA_XML =\r
-            "resources/xml-2009-01.xsd";\r
-    private static final URI EMPTY_URI = URI.create("");\r
-    private static final Class THISCLASS = XmlResourceResolver.class;\r
-\r
-    private final Map<URI, URI> uriMap = new HashMap<URI, URI>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public XmlResourceResolver(){\r
-        super();\r
-\r
-        assert this.getClass().equals(THISCLASS);\r
-\r
-        URI originalURI = URI.create(SCHEMA_XML);\r
-        URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);\r
-        URI redirectURI;\r
-        try{\r
-            redirectURI = redirectURL.toURI();\r
-        }catch(URISyntaxException e){\r
-            assert false;\r
-            throw new AssertionError(e);\r
-        }\r
-\r
-        this.uriMap.put(originalURI, redirectURI);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 絶対URIと相対URIを合成したURIを返す。\r
-     * 正規化も行われる。\r
-     * @param base 絶対URIでなければならない。nullでもよい。\r
-     * @param relative 絶対URIでもよいがその場合baseは無視される。null可。\r
-     * @return 合成結果のURLオブジェクト。必ず絶対URIになる。\r
-     * @throws java.net.URISyntaxException URIとして変。\r
-     * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。\r
-     */\r
-    protected static URI buildBaseRelativeURI(String base, String relative)\r
-            throws URISyntaxException,\r
-                   IllegalArgumentException {\r
-        URI baseURI = null;\r
-        if(base != null){\r
-            baseURI = new URI(base);\r
-            if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();\r
-        }\r
-\r
-        URI relativeURI = EMPTY_URI;\r
-        if(relative != null){\r
-            relativeURI = new URI(relative);\r
-        }\r
-\r
-        URI resultURI;\r
-        if(baseURI == null || relativeURI.isAbsolute()){\r
-            resultURI = relativeURI;\r
-        }else{\r
-            resultURI = baseURI.resolve(relativeURI);\r
-        }\r
-\r
-        if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();\r
-\r
-        resultURI = resultURI.normalize();\r
-\r
-        return resultURI;\r
-    }\r
-\r
-    /**\r
-     * LSInput実装を生成する。\r
-     * @return LSInput実装\r
-     */\r
-    public static LSInput createLSInput(){\r
-        LSInput input = new LSInputImpl();\r
-        return input;\r
-    }\r
-\r
-    /**\r
-     * オリジナルURIとリダイレクト先のURIを登録する。\r
-     * オリジナルURIへのアクセスはリダイレクトされる。\r
-     * @param original オリジナルURI\r
-     * @param redirect リダイレクトURI\r
-     */\r
-    public void putURIMap(URI original, URI redirect){\r
-        this.uriMap.put(original.normalize(), redirect.normalize());\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 変換後のリソースの入力ストリームを得る。\r
-     * @param originalURI オリジナルURI\r
-     * @return 入力ストリーム\r
-     * @throws java.io.IOException 入出力エラー\r
-     */\r
-    public InputStream getXMLResourceAsStream(URI originalURI)\r
-            throws IOException{\r
-        URI resourceURI = this.uriMap.get(originalURI.normalize());\r
-        URL resourceURL = resourceURI.toURL();\r
-        InputStream is = resourceURL.openStream();\r
-\r
-        return is;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * URL変換したあとの入力ソースを返す。\r
-     * @param type {@inheritDoc}\r
-     * @param namespaceURI {@inheritDoc}\r
-     * @param publicId {@inheritDoc}\r
-     * @param systemId {@inheritDoc}\r
-     * @param baseURI {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    @Override\r
-    public LSInput resolveResource(String type,\r
-                                     String namespaceURI,\r
-                                     String publicId,\r
-                                     String systemId,\r
-                                     String baseURI ){\r
-        if(systemId == null) return null;\r
-\r
-        URI originalURI;\r
-        try{\r
-            originalURI = buildBaseRelativeURI(baseURI, systemId);\r
-        }catch(URISyntaxException e){\r
-            return null;\r
-        }\r
-\r
-        InputStream is;\r
-        try{\r
-            is = getXMLResourceAsStream(originalURI);\r
-        }catch(IOException e){\r
-            return null;\r
-        }\r
-\r
-        LSInput input = createLSInput();\r
-        input.setBaseURI(baseURI);\r
-        input.setPublicId(publicId);\r
-        input.setSystemId(systemId);\r
-        input.setByteStream(is);\r
-\r
-        return input;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * URL変換したあとの入力ソースを返す。\r
-     * @param publicId {@inheritDoc}\r
-     * @param systemId {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     * @throws org.xml.sax.SAXException {@inheritDoc}\r
-     * @throws java.io.IOException {@inheritDoc}\r
-     */\r
-    @Override\r
-    public InputSource resolveEntity(String publicId, String systemId)\r
-            throws SAXException, IOException{\r
-        if(systemId == null) return null;\r
-\r
-        URI originalUri;\r
-        try{\r
-            originalUri = new URI(systemId);\r
-        }catch(URISyntaxException e){\r
-            return null;\r
-        }\r
-\r
-        InputStream is = getXMLResourceAsStream(originalUri);\r
-\r
-        InputSource source = new InputSource(is);\r
-        source.setPublicId(publicId);\r
-        source.setSystemId(systemId);\r
-\r
-        return source;\r
-    }\r
-\r
-    /**\r
-     * JRE1.5用LSInput実装。\r
-     * JRE1.6なら\r
-     * org.w3c.dom.ls.DOMImplementationLS#createLSInput()\r
-     * で生成可能かも。\r
-     */\r
-    private static final class LSInputImpl implements LSInput {\r
-\r
-        private String baseURI = null;\r
-        private InputStream byteStream = null;\r
-        private boolean certifiedText = false;\r
-        private Reader characterStream = null;\r
-        private String encoding = null;\r
-        private String publicId = null;\r
-        private String stringData = null;\r
-        private String systemId = null;\r
-\r
-        /**\r
-         * コンストラクタ。\r
-         */\r
-        private LSInputImpl(){\r
-            super();\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public String getBaseURI(){\r
-            return this.baseURI;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param baseURI {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setBaseURI(String baseURI){\r
-            this.baseURI = baseURI;\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public InputStream getByteStream(){\r
-            return this.byteStream;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param byteStream {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setByteStream(InputStream byteStream){\r
-            this.byteStream = byteStream;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public boolean getCertifiedText(){\r
-            return this.certifiedText;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param certifiedText {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setCertifiedText(boolean certifiedText){\r
-            this.certifiedText = certifiedText;\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public Reader getCharacterStream(){\r
-            return this.characterStream;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param characterStream {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setCharacterStream(Reader characterStream){\r
-            this.characterStream = characterStream;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public String getEncoding(){\r
-            return this.encoding;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param encoding {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setEncoding(String encoding){\r
-            this.encoding = encoding;\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public String getPublicId(){\r
-            return this.publicId;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param publicId {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setPublicId(String publicId){\r
-            this.publicId = publicId;\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public String getStringData(){\r
-            return this.stringData;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param stringData {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setStringData(String stringData){\r
-            this.stringData = stringData;\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public String getSystemId(){\r
-            return this.systemId;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * @param systemId {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setSystemId(String systemId){\r
-            this.systemId = systemId;\r
-            return;\r
-        }\r
-\r
-    }\r
-\r
-    // TODO OASIS XML Catalog などと調和したい。\r
-}\r
+/*
+ * xml resource resolver
+ *
+ * License : The MIT License
+ * Copyright(c) 2009 olyutorskii
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
+ * 相対URIはこのクラスをベースに解決される。
+ * 主な用途は外部スキーマのリソース化など。
+ */
+public class XmlResourceResolver
+        implements LSResourceResolver, EntityResolver {
+
+    public static final String SCHEMA_XML =
+            "http://www.w3.org/2001/xml.xsd";
+    public static final String NS_XSD =
+            "http://www.w3.org/2001/XMLSchema-instance";
+
+    private static final String LOCAL_SCHEMA_XML =
+            "resources/xml-2009-01.xsd";
+    private static final URI EMPTY_URI = URI.create("");
+    private static final Class THISCLASS = XmlResourceResolver.class;
+
+    private final Map<URI, URI> uriMap = new HashMap<URI, URI>();
+
+    /**
+     * コンストラクタ。
+     */
+    public XmlResourceResolver(){
+        super();
+
+        assert this.getClass().equals(THISCLASS);
+
+        URI originalURI = URI.create(SCHEMA_XML);
+        URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);
+        URI redirectURI;
+        try{
+            redirectURI = redirectURL.toURI();
+        }catch(URISyntaxException e){
+            assert false;
+            throw new AssertionError(e);
+        }
+
+        this.uriMap.put(originalURI, redirectURI);
+
+        return;
+    }
+
+    /**
+     * 絶対URIと相対URIを合成したURIを返す。
+     * 正規化も行われる。
+     * @param base 絶対URIでなければならない。nullでもよい。
+     * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
+     * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
+     * @throws java.net.URISyntaxException URIとして変。
+     * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
+     */
+    protected static URI buildBaseRelativeURI(String base, String relative)
+            throws URISyntaxException,
+                   IllegalArgumentException {
+        URI baseURI = null;
+        if(base != null){
+            baseURI = new URI(base);
+            if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();
+        }
+
+        URI relativeURI = EMPTY_URI;
+        if(relative != null){
+            relativeURI = new URI(relative);
+        }
+
+        URI resultURI;
+        if(baseURI == null || relativeURI.isAbsolute()){
+            resultURI = relativeURI;
+        }else{
+            resultURI = baseURI.resolve(relativeURI);
+        }
+
+        if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();
+
+        resultURI = resultURI.normalize();
+
+        return resultURI;
+    }
+
+    /**
+     * LSInput実装を生成する。
+     * @return LSInput実装
+     */
+    public static LSInput createLSInput(){
+        LSInput input = new LSInputImpl();
+        return input;
+    }
+
+    /**
+     * オリジナルURIとリダイレクト先のURIを登録する。
+     * オリジナルURIへのアクセスはリダイレクトされる。
+     * @param original オリジナルURI
+     * @param redirect リダイレクトURI
+     */
+    public void putURIMap(URI original, URI redirect){
+        this.uriMap.put(original.normalize(), redirect.normalize());
+        return;
+    }
+
+    /**
+     * 変換後のリソースの入力ストリームを得る。
+     * @param originalURI オリジナルURI
+     * @return 入力ストリーム
+     * @throws java.io.IOException 入出力エラー
+     */
+    public InputStream getXMLResourceAsStream(URI originalURI)
+            throws IOException{
+        URI resourceURI = this.uriMap.get(originalURI.normalize());
+        URL resourceURL = resourceURI.toURL();
+        InputStream is = resourceURL.openStream();
+
+        return is;
+    }
+
+    /**
+     * {@inheritDoc}
+     * URL変換したあとの入力ソースを返す。
+     * @param type {@inheritDoc}
+     * @param namespaceURI {@inheritDoc}
+     * @param publicId {@inheritDoc}
+     * @param systemId {@inheritDoc}
+     * @param baseURI {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public LSInput resolveResource(String type,
+                                     String namespaceURI,
+                                     String publicId,
+                                     String systemId,
+                                     String baseURI ){
+        if(systemId == null) return null;
+
+        URI originalURI;
+        try{
+            originalURI = buildBaseRelativeURI(baseURI, systemId);
+        }catch(URISyntaxException e){
+            return null;
+        }
+
+        InputStream is;
+        try{
+            is = getXMLResourceAsStream(originalURI);
+        }catch(IOException e){
+            return null;
+        }
+
+        LSInput input = createLSInput();
+        input.setBaseURI(baseURI);
+        input.setPublicId(publicId);
+        input.setSystemId(systemId);
+        input.setByteStream(is);
+
+        return input;
+    }
+
+    /**
+     * {@inheritDoc}
+     * URL変換したあとの入力ソースを返す。
+     * @param publicId {@inheritDoc}
+     * @param systemId {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws org.xml.sax.SAXException {@inheritDoc}
+     * @throws java.io.IOException {@inheritDoc}
+     */
+    @Override
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException{
+        if(systemId == null) return null;
+
+        URI originalUri;
+        try{
+            originalUri = new URI(systemId);
+        }catch(URISyntaxException e){
+            return null;
+        }
+
+        InputStream is = getXMLResourceAsStream(originalUri);
+
+        InputSource source = new InputSource(is);
+        source.setPublicId(publicId);
+        source.setSystemId(systemId);
+
+        return source;
+    }
+
+    /**
+     * JRE1.5用LSInput実装。
+     * JRE1.6なら
+     * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
+     * で生成可能かも。
+     */
+    private static final class LSInputImpl implements LSInput {
+
+        private String baseURI = null;
+        private InputStream byteStream = null;
+        private boolean certifiedText = false;
+        private Reader characterStream = null;
+        private String encoding = null;
+        private String publicId = null;
+        private String stringData = null;
+        private String systemId = null;
+
+        /**
+         * コンストラクタ。
+         */
+        private LSInputImpl(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getBaseURI(){
+            return this.baseURI;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param baseURI {@inheritDoc}
+         */
+        @Override
+        public void setBaseURI(String baseURI){
+            this.baseURI = baseURI;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public InputStream getByteStream(){
+            return this.byteStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param byteStream {@inheritDoc}
+         */
+        @Override
+        public void setByteStream(InputStream byteStream){
+            this.byteStream = byteStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public boolean getCertifiedText(){
+            return this.certifiedText;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param certifiedText {@inheritDoc}
+         */
+        @Override
+        public void setCertifiedText(boolean certifiedText){
+            this.certifiedText = certifiedText;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public Reader getCharacterStream(){
+            return this.characterStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param characterStream {@inheritDoc}
+         */
+        @Override
+        public void setCharacterStream(Reader characterStream){
+            this.characterStream = characterStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getEncoding(){
+            return this.encoding;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param encoding {@inheritDoc}
+         */
+        @Override
+        public void setEncoding(String encoding){
+            this.encoding = encoding;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getPublicId(){
+            return this.publicId;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param publicId {@inheritDoc}
+         */
+        @Override
+        public void setPublicId(String publicId){
+            this.publicId = publicId;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getStringData(){
+            return this.stringData;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param stringData {@inheritDoc}
+         */
+        @Override
+        public void setStringData(String stringData){
+            this.stringData = stringData;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getSystemId(){
+            return this.systemId;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param systemId {@inheritDoc}
+         */
+        @Override
+        public void setSystemId(String systemId){
+            this.systemId = systemId;
+            return;
+        }
+
+    }
+
+    // TODO OASIS XML Catalog などと調和したい。
+}
index 7514231..7a03281 100644 (file)
@@ -1,14 +1,14 @@
-/*\r
- * package information for Javadoc\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-/**\r
- * MikuToga XML共通ライブラリ。\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\r
-\r
-/* EOF */\r
+/*
+ * package information for Javadoc
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+/**
+ * MikuToga XML共通ライブラリ。
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+/* EOF */
index 9ecbfc5..851f3aa 100644 (file)
-<?xml version="1.0" encoding="UTF-8" ?>\r
-\r
-<!--\r
-  MikuMikuDance\r
-    model-data(*.pmd) on XML\r
-    DTD definition\r
-\r
-  License : The MIT License\r
-  Copyright(c) 2010 MikuToga Partners\r
-\r
-  SYSTEM ID: http://mikutoga.sourceforge.jp/xml/dtd/pmdxml-101009.dtd\r
--->\r
-\r
-\r
-<!-- ROOT -->\r
-<!ELEMENT pmdModel (\r
-    i18nName*, description+, license*, credits*, meta*,\r
-    materialList,\r
-    toonMap,\r
-    boneList,\r
-    boneGroupList,\r
-    ikChainList,\r
-    morphList,\r
-    rigidList,\r
-    rigidGroupList,\r
-    jointList,\r
-    surfaceGroupList,\r
-    vertexList\r
-) >\r
-<!ATTLIST pmdModel\r
-    xmlns              CDATA #IMPLIED\r
-    xmlns:xsi          CDATA #IMPLIED\r
-    xsi:schemaLocation CDATA #IMPLIED\r
-    schemaVersion      CDATA #FIXED "100923"\r
-    name               CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Multilingual name. -->\r
-<!ELEMENT i18nName EMPTY>\r
-<!ATTLIST i18nName\r
-    lang CDATA #REQUIRED\r
-    name CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Break line. -->\r
-<!ELEMENT br EMPTY>\r
-\r
-\r
-<!-- Description note about model. -->\r
-<!ELEMENT description (#PCDATA | br)* >\r
-<!ATTLIST description\r
-    lang      CDATA "ja"\r
-    xml:space CDATA #FIXED "preserve"\r
->\r
-\r
-\r
-<!-- License term of usage. -->\r
-<!ELEMENT license (#PCDATA | br)* >\r
-<!ATTLIST license\r
-    lang      CDATA "ja"\r
-    xml:space CDATA #FIXED "preserve"\r
->\r
-\r
-\r
-<!-- Credits for someone. -->\r
-<!ELEMENT credits (#PCDATA | br)* >\r
-<!ATTLIST credits\r
-    lang      CDATA "ja"\r
-    xml:space CDATA #FIXED "preserve"\r
->\r
-\r
-\r
-<!--\r
-Meta-information of model.\r
-Use free.\r
-but, some meta-name has recommended usage.\r
-+ "generator" (Generator application name)\r
-+ "siteURL" (Website URL)\r
-+ "imageURL" (Thumbnail image URL)\r
--->\r
-<!ELEMENT meta EMPTY>\r
-<!ATTLIST meta\r
-    name    CDATA #REQUIRED\r
-    content CDATA #REQUIRED\r
->\r
-\r
-\r
-<!--\r
-Material list.\r
-All visual things can be tracked from here.\r
--->\r
-<!ELEMENT materialList (material)* >\r
-\r
-\r
-<!--\r
-Material definition.\r
-Colors, shading, any other definitions.\r
--->\r
-<!ELEMENT material (\r
-    i18nName*,\r
-    diffuse,\r
-    specular,\r
-    ambient,\r
-    toon?,\r
-    textureFile?,\r
-    spheremapFile?\r
-)*>\r
-<!ATTLIST material\r
-    name              CDATA #IMPLIED\r
-    showEdge          CDATA #REQUIRED\r
-    surfaceGroupIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Diffuse color definition. -->\r
-<!ELEMENT diffuse EMPTY>\r
-<!ATTLIST diffuse\r
-    r     CDATA #REQUIRED\r
-    g     CDATA #REQUIRED\r
-    b     CDATA #REQUIRED\r
-    alpha CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Specular color definition. -->\r
-<!ELEMENT specular EMPTY>\r
-<!ATTLIST specular\r
-    r         CDATA #REQUIRED\r
-    g         CDATA #REQUIRED\r
-    b         CDATA #REQUIRED\r
-    shininess CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Ambient color definition. -->\r
-<!ELEMENT ambient EMPTY>\r
-<!ATTLIST ambient\r
-    r CDATA #REQUIRED\r
-    g CDATA #REQUIRED\r
-    b CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Reference for Toon-image. -->\r
-<!ELEMENT toon EMPTY>\r
-<!ATTLIST toon\r
-    toonFileIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Texture file information. -->\r
-<!ELEMENT textureFile EMPTY>\r
-<!ATTLIST textureFile\r
-    winFileName CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Sphere-map file information. -->\r
-<!ELEMENT spheremapFile EMPTY>\r
-<!ATTLIST spheremapFile\r
-    winFileName CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Toon-file mappings. -->\r
-<!ELEMENT toonMap (toonDef)* >\r
-\r
-\r
-<!-- Toon-file information. -->\r
-<!ELEMENT toonDef EMPTY>\r
-<!ATTLIST toonDef\r
-    toonFileId  CDATA #REQUIRED\r
-    index       CDATA #REQUIRED\r
-    winFileName CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of bone information. -->\r
-<!ELEMENT boneList (bone)* >\r
-\r
-\r
-<!-- Bone definition. -->\r
-<!ELEMENT bone (\r
-    i18nName*,\r
-    position,\r
-    (rotationRatio | ikBone)?,\r
-    boneChain\r
-) >\r
-<!ATTLIST bone\r
-    name   CDATA #REQUIRED\r
-    boneId CDATA #REQUIRED\r
-    type   (\r
-          ROTATE\r
-        | ROTMOV\r
-        | IK\r
-        | UNKNOWN\r
-        | UNDERIK\r
-        | UNDERROT\r
-        | IKCONNECTED\r
-        | HIDDEN\r
-        | TWIST\r
-        | LINKEDROT\r
-    ) #REQUIRED\r
->\r
-\r
-\r
-<!-- position information. -->\r
-<!ELEMENT position EMPTY>\r
-<!ATTLIST position\r
-    x CDATA #REQUIRED\r
-    y CDATA #REQUIRED\r
-    z CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Relationship-info between bones. -->\r
-<!ELEMENT boneChain EMPTY>\r
-<!ATTLIST boneChain\r
-    prevBoneIdRef CDATA #IMPLIED\r
-    nextBoneIdRef CDATA #IMPLIED\r
->\r
-\r
-\r
-<!-- Rotation ratio between Linked-rotationed bones. -->\r
-<!ELEMENT rotationRatio EMPTY>\r
-<!ATTLIST rotationRatio\r
-    ratio CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Reference to IK-Bone. -->\r
-<!ELEMENT ikBone EMPTY>\r
-<!ATTLIST ikBone\r
-    boneIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of Bone-group. -->\r
-<!ELEMENT boneGroupList (boneGroup)* >\r
-\r
-\r
-<!-- Bone-group. -->\r
-<!ELEMENT boneGroup (i18nName*, boneGroupMember*) >\r
-<!ATTLIST boneGroup\r
-    name CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Member of Bone-group. -->\r
-<!ELEMENT boneGroupMember EMPTY>\r
-<!ATTLIST boneGroupMember\r
-    boneIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of IK chain. -->\r
-<!ELEMENT ikChainList (ikChain)* >\r
-\r
-\r
-<!-- IK chained bones definition. -->\r
-<!ELEMENT ikChain (chainOrder)+ >\r
-<!ATTLIST ikChain\r
-    ikBoneIdRef    CDATA #REQUIRED\r
-    recursiveDepth CDATA #REQUIRED\r
-    weight         CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Part of IK chained bones. -->\r
-<!ELEMENT chainOrder EMPTY>\r
-<!ATTLIST chainOrder\r
-    boneIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of morphing definition. -->\r
-<!ELEMENT morphList (morph)* >\r
-\r
-\r
-<!-- Morphing definition. -->\r
-<!ELEMENT morph (i18nName*, morphVertex*) >\r
-<!ATTLIST morph\r
-    name CDATA #REQUIRED\r
-    type (\r
-          EYEBROW\r
-        | EYE\r
-        | LIP\r
-        | EXTRA\r
-    ) #REQUIRED\r
->\r
-\r
-\r
-<!-- Morphing vertex information. -->\r
-<!ELEMENT morphVertex EMPTY>\r
-<!ATTLIST morphVertex\r
-    vtxIdRef CDATA #REQUIRED\r
-    xOff     CDATA #REQUIRED\r
-    yOff     CDATA #REQUIRED\r
-    zOff     CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- list of Rigid-body definition. -->\r
-<!ELEMENT rigidList (rigid)* >\r
-\r
-\r
-<!-- Rigid-body definition. -->\r
-<!ELEMENT rigid (\r
-    i18nName*,\r
-    linkedBone?,\r
-    (rigidShapeSphere | rigidShapeBox | rigidShapeCapsule),\r
-    position,\r
-    radRotation,\r
-    dynamics,\r
-    throughRigidGroup*\r
-) >\r
-<!ATTLIST rigid\r
-    name     CDATA #REQUIRED\r
-    rigidId  CDATA #REQUIRED\r
-    behavior (\r
-          FOLLOWBONE\r
-        | ONLYDYNAMICS\r
-        | BONEDDYNAMICS\r
-    ) #REQUIRED\r
->\r
-\r
-\r
-<!-- Referenced Bone from Rigid-body. -->\r
-<!ELEMENT linkedBone EMPTY>\r
-<!ATTLIST linkedBone\r
-    boneIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Sphere shape of Rigid-body. -->\r
-<!ELEMENT rigidShapeSphere EMPTY>\r
-<!ATTLIST rigidShapeSphere\r
-    radius CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Box shape of Rigid-body. -->\r
-<!ELEMENT rigidShapeBox EMPTY>\r
-<!ATTLIST rigidShapeBox\r
-    width  CDATA #REQUIRED\r
-    height CDATA #REQUIRED\r
-    depth  CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Capsule shape of Rigid-body. -->\r
-<!ELEMENT rigidShapeCapsule EMPTY>\r
-<!ATTLIST rigidShapeCapsule\r
-    height CDATA #REQUIRED\r
-    radius CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Rotaion information by radian. -->\r
-<!ELEMENT radRotation EMPTY>\r
-<!ATTLIST radRotation\r
-    xRad CDATA #REQUIRED\r
-    yRad CDATA #REQUIRED\r
-    zRad CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Dynamics parameters. -->\r
-<!ELEMENT dynamics EMPTY>\r
-<!ATTLIST dynamics\r
-    mass            CDATA #REQUIRED\r
-    dampingPosition CDATA #REQUIRED\r
-    dampingRotation CDATA #REQUIRED\r
-    restitution     CDATA #REQUIRED\r
-    friction        CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Reference for non-collision rigid-group. -->\r
-<!ELEMENT throughRigidGroup EMPTY>\r
-<!ATTLIST throughRigidGroup\r
-    rigidGroupIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of Rigid-body group. -->\r
-<!ELEMENT rigidGroupList (rigidGroup)* >\r
-\r
-\r
-<!-- Rigid-body group. -->\r
-<!ELEMENT rigidGroup (rigidGroupMember)* >\r
-<!ATTLIST rigidGroup\r
-    rigidGroupId CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Member of Rigid-body group. -->\r
-<!ELEMENT rigidGroupMember EMPTY>\r
-<!ATTLIST rigidGroupMember\r
-    rigidIdRef CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of joint definition. -->\r
-<!ELEMENT jointList (joint)* >\r
-\r
-\r
-<!-- Joint definition. -->\r
-<!ELEMENT joint (\r
-    i18nName*,\r
-    jointedRigidPair,\r
-    position,    limitPosition,\r
-    radRotation, limitRotation,\r
-    elasticPosition,\r
-    elasticRotation\r
-) >\r
-<!ATTLIST joint\r
-    name CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Jointed-bones information. -->\r
-<!ELEMENT jointedRigidPair EMPTY>\r
-<!ATTLIST jointedRigidPair\r
-    rigidIdRef2 CDATA #REQUIRED\r
-    rigidIdRef1 CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Limit of Position. -->\r
-<!ELEMENT limitPosition EMPTY>\r
-<!ATTLIST limitPosition\r
-    xFrom CDATA #REQUIRED\r
-    xTo   CDATA #REQUIRED\r
-    yFrom CDATA #REQUIRED\r
-    yTo   CDATA #REQUIRED\r
-    zFrom CDATA #REQUIRED\r
-    zTo   CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Limit of Rotation. -->\r
-<!ELEMENT limitRotation EMPTY>\r
-<!ATTLIST limitRotation\r
-    xFrom CDATA #REQUIRED\r
-    xTo   CDATA #REQUIRED\r
-    yFrom CDATA #REQUIRED\r
-    yTo   CDATA #REQUIRED\r
-    zFrom CDATA #REQUIRED\r
-    zTo   CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Elastic position of joint. -->\r
-<!ELEMENT elasticPosition EMPTY>\r
-<!ATTLIST elasticPosition\r
-    x CDATA #REQUIRED\r
-    y CDATA #REQUIRED\r
-    z CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Elastic rotation of joint by degree. -->\r
-<!ELEMENT elasticRotation EMPTY>\r
-<!ATTLIST elasticRotation\r
-    xDeg CDATA #REQUIRED\r
-    yDeg CDATA #REQUIRED\r
-    zDeg CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of surface group. -->\r
-<!ELEMENT surfaceGroupList (surfaceGroup)* >\r
-\r
-\r
-<!-- Surface group. -->\r
-<!ELEMENT surfaceGroup (surface)* >\r
-<!ATTLIST surfaceGroup\r
-    surfaceGroupId CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Each surface with Triangle. -->\r
-<!ELEMENT surface EMPTY>\r
-<!ATTLIST surface\r
-    vtxIdRef1 CDATA #REQUIRED\r
-    vtxIdRef2 CDATA #REQUIRED\r
-    vtxIdRef3 CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- List of vertex. -->\r
-<!ELEMENT vertexList (vertex)* >\r
-\r
-\r
-<!-- Vertex definition. -->\r
-<!ELEMENT vertex (position, normal, uvMap, skinning) >\r
-<!ATTLIST vertex\r
-    vtxId    CDATA #REQUIRED\r
-    showEdge CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Normal vector definition. -->\r
-<!ELEMENT normal EMPTY>\r
-<!ATTLIST normal\r
-    x CDATA #REQUIRED\r
-    y CDATA #REQUIRED\r
-    z CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- UV-mapping information. -->\r
-<!ELEMENT uvMap EMPTY>\r
-<!ATTLIST uvMap\r
-    u CDATA #REQUIRED\r
-    v CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- Skinning definition from vertex to bone. -->\r
-<!ELEMENT skinning EMPTY>\r
-<!ATTLIST skinning\r
-    boneIdRef1    CDATA #REQUIRED\r
-    boneIdRef2    CDATA #REQUIRED\r
-    weightBalance CDATA #REQUIRED\r
->\r
-\r
-\r
-<!-- EOF -->\r
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+  MikuMikuDance
+    model-data(*.pmd) on XML
+    DTD definition
+
+  License : The MIT License
+  Copyright(c) 2010 MikuToga Partners
+
+  SYSTEM ID: http://mikutoga.sourceforge.jp/xml/dtd/pmdxml-101009.dtd
+-->
+
+
+<!-- ROOT -->
+<!ELEMENT pmdModel (
+    i18nName*, description+, license*, credits*, meta*,
+    materialList,
+    toonMap,
+    boneList,
+    boneGroupList,
+    ikChainList,
+    morphList,
+    rigidList,
+    rigidGroupList,
+    jointList,
+    surfaceGroupList,
+    vertexList
+) >
+<!ATTLIST pmdModel
+    xmlns              CDATA #IMPLIED
+    xmlns:xsi          CDATA #IMPLIED
+    xsi:schemaLocation CDATA #IMPLIED
+    schemaVersion      CDATA #FIXED "100923"
+    name               CDATA #REQUIRED
+>
+
+
+<!-- Multilingual name. -->
+<!ELEMENT i18nName EMPTY>
+<!ATTLIST i18nName
+    lang CDATA #REQUIRED
+    name CDATA #REQUIRED
+>
+
+
+<!-- Break line. -->
+<!ELEMENT br EMPTY>
+
+
+<!-- Description note about model. -->
+<!ELEMENT description (#PCDATA | br)* >
+<!ATTLIST description
+    lang      CDATA "ja"
+    xml:space CDATA #FIXED "preserve"
+>
+
+
+<!-- License term of usage. -->
+<!ELEMENT license (#PCDATA | br)* >
+<!ATTLIST license
+    lang      CDATA "ja"
+    xml:space CDATA #FIXED "preserve"
+>
+
+
+<!-- Credits for someone. -->
+<!ELEMENT credits (#PCDATA | br)* >
+<!ATTLIST credits
+    lang      CDATA "ja"
+    xml:space CDATA #FIXED "preserve"
+>
+
+
+<!--
+Meta-information of model.
+Use free.
+but, some meta-name has recommended usage.
++ "generator" (Generator application name)
++ "siteURL" (Website URL)
++ "imageURL" (Thumbnail image URL)
+-->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+    name    CDATA #REQUIRED
+    content CDATA #REQUIRED
+>
+
+
+<!--
+Material list.
+All visual things can be tracked from here.
+-->
+<!ELEMENT materialList (material)* >
+
+
+<!--
+Material definition.
+Colors, shading, any other definitions.
+-->
+<!ELEMENT material (
+    i18nName*,
+    diffuse,
+    specular,
+    ambient,
+    toon?,
+    textureFile?,
+    spheremapFile?
+)*>
+<!ATTLIST material
+    name              CDATA #IMPLIED
+    showEdge          CDATA #REQUIRED
+    surfaceGroupIdRef CDATA #REQUIRED
+>
+
+
+<!-- Diffuse color definition. -->
+<!ELEMENT diffuse EMPTY>
+<!ATTLIST diffuse
+    r     CDATA #REQUIRED
+    g     CDATA #REQUIRED
+    b     CDATA #REQUIRED
+    alpha CDATA #REQUIRED
+>
+
+
+<!-- Specular color definition. -->
+<!ELEMENT specular EMPTY>
+<!ATTLIST specular
+    r         CDATA #REQUIRED
+    g         CDATA #REQUIRED
+    b         CDATA #REQUIRED
+    shininess CDATA #REQUIRED
+>
+
+
+<!-- Ambient color definition. -->
+<!ELEMENT ambient EMPTY>
+<!ATTLIST ambient
+    r CDATA #REQUIRED
+    g CDATA #REQUIRED
+    b CDATA #REQUIRED
+>
+
+
+<!-- Reference for Toon-image. -->
+<!ELEMENT toon EMPTY>
+<!ATTLIST toon
+    toonFileIdRef CDATA #REQUIRED
+>
+
+
+<!-- Texture file information. -->
+<!ELEMENT textureFile EMPTY>
+<!ATTLIST textureFile
+    winFileName CDATA #REQUIRED
+>
+
+
+<!-- Sphere-map file information. -->
+<!ELEMENT spheremapFile EMPTY>
+<!ATTLIST spheremapFile
+    winFileName CDATA #REQUIRED
+>
+
+
+<!-- Toon-file mappings. -->
+<!ELEMENT toonMap (toonDef)* >
+
+
+<!-- Toon-file information. -->
+<!ELEMENT toonDef EMPTY>
+<!ATTLIST toonDef
+    toonFileId  CDATA #REQUIRED
+    index       CDATA #REQUIRED
+    winFileName CDATA #REQUIRED
+>
+
+
+<!-- List of bone information. -->
+<!ELEMENT boneList (bone)* >
+
+
+<!-- Bone definition. -->
+<!ELEMENT bone (
+    i18nName*,
+    position,
+    (rotationRatio | ikBone)?,
+    boneChain
+) >
+<!ATTLIST bone
+    name   CDATA #REQUIRED
+    boneId CDATA #REQUIRED
+    type   (
+          ROTATE
+        | ROTMOV
+        | IK
+        | UNKNOWN
+        | UNDERIK
+        | UNDERROT
+        | IKCONNECTED
+        | HIDDEN
+        | TWIST
+        | LINKEDROT
+    ) #REQUIRED
+>
+
+
+<!-- position information. -->
+<!ELEMENT position EMPTY>
+<!ATTLIST position
+    x CDATA #REQUIRED
+    y CDATA #REQUIRED
+    z CDATA #REQUIRED
+>
+
+
+<!-- Relationship-info between bones. -->
+<!ELEMENT boneChain EMPTY>
+<!ATTLIST boneChain
+    prevBoneIdRef CDATA #IMPLIED
+    nextBoneIdRef CDATA #IMPLIED
+>
+
+
+<!-- Rotation ratio between Linked-rotationed bones. -->
+<!ELEMENT rotationRatio EMPTY>
+<!ATTLIST rotationRatio
+    ratio CDATA #REQUIRED
+>
+
+
+<!-- Reference to IK-Bone. -->
+<!ELEMENT ikBone EMPTY>
+<!ATTLIST ikBone
+    boneIdRef CDATA #REQUIRED
+>
+
+
+<!-- List of Bone-group. -->
+<!ELEMENT boneGroupList (boneGroup)* >
+
+
+<!-- Bone-group. -->
+<!ELEMENT boneGroup (i18nName*, boneGroupMember*) >
+<!ATTLIST boneGroup
+    name CDATA #REQUIRED
+>
+
+
+<!-- Member of Bone-group. -->
+<!ELEMENT boneGroupMember EMPTY>
+<!ATTLIST boneGroupMember
+    boneIdRef CDATA #REQUIRED
+>
+
+
+<!-- List of IK chain. -->
+<!ELEMENT ikChainList (ikChain)* >
+
+
+<!-- IK chained bones definition. -->
+<!ELEMENT ikChain (chainOrder)+ >
+<!ATTLIST ikChain
+    ikBoneIdRef    CDATA #REQUIRED
+    recursiveDepth CDATA #REQUIRED
+    weight         CDATA #REQUIRED
+>
+
+
+<!-- Part of IK chained bones. -->
+<!ELEMENT chainOrder EMPTY>
+<!ATTLIST chainOrder
+    boneIdRef CDATA #REQUIRED
+>
+
+
+<!-- List of morphing definition. -->
+<!ELEMENT morphList (morph)* >
+
+
+<!-- Morphing definition. -->
+<!ELEMENT morph (i18nName*, morphVertex*) >
+<!ATTLIST morph
+    name CDATA #REQUIRED
+    type (
+          EYEBROW
+        | EYE
+        | LIP
+        | EXTRA
+    ) #REQUIRED
+>
+
+
+<!-- Morphing vertex information. -->
+<!ELEMENT morphVertex EMPTY>
+<!ATTLIST morphVertex
+    vtxIdRef CDATA #REQUIRED
+    xOff     CDATA #REQUIRED
+    yOff     CDATA #REQUIRED
+    zOff     CDATA #REQUIRED
+>
+
+
+<!-- list of Rigid-body definition. -->
+<!ELEMENT rigidList (rigid)* >
+
+
+<!-- Rigid-body definition. -->
+<!ELEMENT rigid (
+    i18nName*,
+    linkedBone?,
+    (rigidShapeSphere | rigidShapeBox | rigidShapeCapsule),
+    position,
+    radRotation,
+    dynamics,
+    throughRigidGroup*
+) >
+<!ATTLIST rigid
+    name     CDATA #REQUIRED
+    rigidId  CDATA #REQUIRED
+    behavior (
+          FOLLOWBONE
+        | ONLYDYNAMICS
+        | BONEDDYNAMICS
+    ) #REQUIRED
+>
+
+
+<!-- Referenced Bone from Rigid-body. -->
+<!ELEMENT linkedBone EMPTY>
+<!ATTLIST linkedBone
+    boneIdRef CDATA #REQUIRED
+>
+
+
+<!-- Sphere shape of Rigid-body. -->
+<!ELEMENT rigidShapeSphere EMPTY>
+<!ATTLIST rigidShapeSphere
+    radius CDATA #REQUIRED
+>
+
+
+<!-- Box shape of Rigid-body. -->
+<!ELEMENT rigidShapeBox EMPTY>
+<!ATTLIST rigidShapeBox
+    width  CDATA #REQUIRED
+    height CDATA #REQUIRED
+    depth  CDATA #REQUIRED
+>
+
+
+<!-- Capsule shape of Rigid-body. -->
+<!ELEMENT rigidShapeCapsule EMPTY>
+<!ATTLIST rigidShapeCapsule
+    height CDATA #REQUIRED
+    radius CDATA #REQUIRED
+>
+
+
+<!-- Rotaion information by radian. -->
+<!ELEMENT radRotation EMPTY>
+<!ATTLIST radRotation
+    xRad CDATA #REQUIRED
+    yRad CDATA #REQUIRED
+    zRad CDATA #REQUIRED
+>
+
+
+<!-- Dynamics parameters. -->
+<!ELEMENT dynamics EMPTY>
+<!ATTLIST dynamics
+    mass            CDATA #REQUIRED
+    dampingPosition CDATA #REQUIRED
+    dampingRotation CDATA #REQUIRED
+    restitution     CDATA #REQUIRED
+    friction        CDATA #REQUIRED
+>
+
+
+<!-- Reference for non-collision rigid-group. -->
+<!ELEMENT throughRigidGroup EMPTY>
+<!ATTLIST throughRigidGroup
+    rigidGroupIdRef CDATA #REQUIRED
+>
+
+
+<!-- List of Rigid-body group. -->
+<!ELEMENT rigidGroupList (rigidGroup)* >
+
+
+<!-- Rigid-body group. -->
+<!ELEMENT rigidGroup (rigidGroupMember)* >
+<!ATTLIST rigidGroup
+    rigidGroupId CDATA #REQUIRED
+>
+
+
+<!-- Member of Rigid-body group. -->
+<!ELEMENT rigidGroupMember EMPTY>
+<!ATTLIST rigidGroupMember
+    rigidIdRef CDATA #REQUIRED
+>
+
+
+<!-- List of joint definition. -->
+<!ELEMENT jointList (joint)* >
+
+
+<!-- Joint definition. -->
+<!ELEMENT joint (
+    i18nName*,
+    jointedRigidPair,
+    position,    limitPosition,
+    radRotation, limitRotation,
+    elasticPosition,
+    elasticRotation
+) >
+<!ATTLIST joint
+    name CDATA #REQUIRED
+>
+
+
+<!-- Jointed-bones information. -->
+<!ELEMENT jointedRigidPair EMPTY>
+<!ATTLIST jointedRigidPair
+    rigidIdRef2 CDATA #REQUIRED
+    rigidIdRef1 CDATA #REQUIRED
+>
+
+
+<!-- Limit of Position. -->
+<!ELEMENT limitPosition EMPTY>
+<!ATTLIST limitPosition
+    xFrom CDATA #REQUIRED
+    xTo   CDATA #REQUIRED
+    yFrom CDATA #REQUIRED
+    yTo   CDATA #REQUIRED
+    zFrom CDATA #REQUIRED
+    zTo   CDATA #REQUIRED
+>
+
+
+<!-- Limit of Rotation. -->
+<!ELEMENT limitRotation EMPTY>
+<!ATTLIST limitRotation
+    xFrom CDATA #REQUIRED
+    xTo   CDATA #REQUIRED
+    yFrom CDATA #REQUIRED
+    yTo   CDATA #REQUIRED
+    zFrom CDATA #REQUIRED
+    zTo   CDATA #REQUIRED
+>
+
+
+<!-- Elastic position of joint. -->
+<!ELEMENT elasticPosition EMPTY>
+<!ATTLIST elasticPosition
+    x CDATA #REQUIRED
+    y CDATA #REQUIRED
+    z CDATA #REQUIRED
+>
+
+
+<!-- Elastic rotation of joint by degree. -->
+<!ELEMENT elasticRotation EMPTY>
+<!ATTLIST elasticRotation
+    xDeg CDATA #REQUIRED
+    yDeg CDATA #REQUIRED
+    zDeg CDATA #REQUIRED
+>
+
+
+<!-- List of surface group. -->
+<!ELEMENT surfaceGroupList (surfaceGroup)* >
+
+
+<!-- Surface group. -->
+<!ELEMENT surfaceGroup (surface)* >
+<!ATTLIST surfaceGroup
+    surfaceGroupId CDATA #REQUIRED
+>
+
+
+<!-- Each surface with Triangle. -->
+<!ELEMENT surface EMPTY>
+<!ATTLIST surface
+    vtxIdRef1 CDATA #REQUIRED
+    vtxIdRef2 CDATA #REQUIRED
+    vtxIdRef3 CDATA #REQUIRED
+>
+
+
+<!-- List of vertex. -->
+<!ELEMENT vertexList (vertex)* >
+
+
+<!-- Vertex definition. -->
+<!ELEMENT vertex (position, normal, uvMap, skinning) >
+<!ATTLIST vertex
+    vtxId    CDATA #REQUIRED
+    showEdge CDATA #REQUIRED
+>
+
+
+<!-- Normal vector definition. -->
+<!ELEMENT normal EMPTY>
+<!ATTLIST normal
+    x CDATA #REQUIRED
+    y CDATA #REQUIRED
+    z CDATA #REQUIRED
+>
+
+
+<!-- UV-mapping information. -->
+<!ELEMENT uvMap EMPTY>
+<!ATTLIST uvMap
+    u CDATA #REQUIRED
+    v CDATA #REQUIRED
+>
+
+
+<!-- Skinning definition from vertex to bone. -->
+<!ELEMENT skinning EMPTY>
+<!ATTLIST skinning
+    boneIdRef1    CDATA #REQUIRED
+    boneIdRef2    CDATA #REQUIRED
+    weightBalance CDATA #REQUIRED
+>
+
+
+<!-- EOF -->
index a135013..f8a313c 100644 (file)
@@ -1,47 +1,47 @@
-/*\r
- *\r
- */\r
-\r
-package jp.sourceforge.mikutoga.parser;\r
-\r
-import junit.framework.TestCase;\r
-import org.junit.Test;\r
-\r
-/**\r
- *\r
- */\r
-public class ParseStageTest extends TestCase {\r
-\r
-    public ParseStageTest(String testName) {\r
-        super(testName);\r
-    }\r
-\r
-    @Override\r
-    protected void setUp() throws Exception {\r
-        super.setUp();\r
-    }\r
-\r
-    @Override\r
-    protected void tearDown() throws Exception {\r
-        super.tearDown();\r
-    }\r
-\r
-    /**\r
-     * Test of toString method, of class ParseStage.\r
-     */\r
-    @Test\r
-    public void testToString(){\r
-        System.out.println("toString");\r
-\r
-        ParseStage instance;\r
-\r
-        instance = new ParseStage();\r
-        assertEquals("", instance.toString());\r
-\r
-        instance = new ParseStage("ABC");\r
-        assertEquals("ABC", instance.toString());\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ *
+ */
+
+package jp.sourceforge.mikutoga.parser;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class ParseStageTest extends TestCase {
+
+    public ParseStageTest(String testName) {
+        super(testName);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test of toString method, of class ParseStage.
+     */
+    @Test
+    public void testToString(){
+        System.out.println("toString");
+
+        ParseStage instance;
+
+        instance = new ParseStage();
+        assertEquals("", instance.toString());
+
+        instance = new ParseStage("ABC");
+        assertEquals("ABC", instance.toString());
+
+        return;
+    }
+
+}
index 21f3d36..3608a2b 100644 (file)
-/*\r
- *\r
- */\r
-\r
-package jp.sourceforge.mikutoga.pmd;\r
-\r
-import java.util.Locale;\r
-import org.junit.After;\r
-import org.junit.AfterClass;\r
-import org.junit.Before;\r
-import org.junit.BeforeClass;\r
-import org.junit.Test;\r
-import static org.junit.Assert.*;\r
-\r
-/**\r
- * \r
- */\r
-public class MorphTypeTest {\r
-\r
-    public MorphTypeTest() {\r
-    }\r
-\r
-    @BeforeClass\r
-    public static void setUpClass() throws Exception{\r
-    }\r
-\r
-    @AfterClass\r
-    public static void tearDownClass() throws Exception{\r
-    }\r
-\r
-    @Before\r
-    public void setUp() {\r
-    }\r
-\r
-    @After\r
-    public void tearDown() {\r
-    }\r
-\r
-    /**\r
-     * Test of values method, of class MorphType.\r
-     */\r
-    @Test\r
-    public void testValues(){\r
-        System.out.println("values");\r
-\r
-        MorphType[] array = MorphType.values();\r
-\r
-        assertEquals(5, array.length);\r
-\r
-        assertEquals(MorphType.BASE, array[0]);\r
-        assertEquals(MorphType.EYEBROW, array[1]);\r
-        assertEquals(MorphType.EYE, array[2]);\r
-        assertEquals(MorphType.LIP, array[3]);\r
-        assertEquals(MorphType.EXTRA, array[4]);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Test of decode method, of class MorphType.\r
-     */\r
-    @Test\r
-    public void testDecode(){\r
-        System.out.println("decode");\r
-\r
-        assertEquals(MorphType.BASE,    MorphType.decode((byte)0x00));\r
-        assertEquals(MorphType.EYEBROW, MorphType.decode((byte)0x01));\r
-        assertEquals(MorphType.EYE,     MorphType.decode((byte)0x02));\r
-        assertEquals(MorphType.LIP,     MorphType.decode((byte)0x03));\r
-        assertEquals(MorphType.EXTRA,   MorphType.decode((byte)0x04));\r
-        assertNull(MorphType.decode((byte)0x05));\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Test of encode method, of class MorphType.\r
-     */\r
-    @Test\r
-    public void testEncode(){\r
-        System.out.println("encode");\r
-\r
-        assertEquals(0x00, MorphType.BASE.encode());\r
-        assertEquals(0x01, MorphType.EYEBROW.encode());\r
-        assertEquals(0x02, MorphType.EYE.encode());\r
-        assertEquals(0x03, MorphType.LIP.encode());\r
-        assertEquals(0x04, MorphType.EXTRA.encode());\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Test of getGuiName method, of class MorphType.\r
-     */\r
-    @Test\r
-    public void testGetGuiName_0args(){\r
-        System.out.println("getGuiName");\r
-\r
-        Locale locale = Locale.getDefault();\r
-\r
-        for(MorphType type : MorphType.values()){\r
-            assertEquals(type.getGuiName(locale), type.getGuiName());\r
-        }\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Test of getGuiName method, of class MorphType.\r
-     */\r
-    @Test\r
-    public void testGetGuiName_Locale(){\r
-        System.out.println("getGuiName");\r
-\r
-        Locale locale = Locale.JAPANESE;\r
-\r
-        assertEquals("base", MorphType.BASE.getGuiName(locale));\r
-        assertEquals("まゆ", MorphType.EYEBROW.getGuiName(locale));\r
-        assertEquals("目", MorphType.EYE.getGuiName(locale));\r
-        assertEquals("リップ", MorphType.LIP.getGuiName(locale));\r
-        assertEquals("その他", MorphType.EXTRA.getGuiName(locale));\r
-        \r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ *
+ */
+
+package jp.sourceforge.mikutoga.pmd;
+
+import java.util.Locale;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * 
+ */
+public class MorphTypeTest {
+
+    public MorphTypeTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception{
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception{
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of values method, of class MorphType.
+     */
+    @Test
+    public void testValues(){
+        System.out.println("values");
+
+        MorphType[] array = MorphType.values();
+
+        assertEquals(5, array.length);
+
+        assertEquals(MorphType.BASE, array[0]);
+        assertEquals(MorphType.EYEBROW, array[1]);
+        assertEquals(MorphType.EYE, array[2]);
+        assertEquals(MorphType.LIP, array[3]);
+        assertEquals(MorphType.EXTRA, array[4]);
+
+        return;
+    }
+
+    /**
+     * Test of decode method, of class MorphType.
+     */
+    @Test
+    public void testDecode(){
+        System.out.println("decode");
+
+        assertEquals(MorphType.BASE,    MorphType.decode((byte)0x00));
+        assertEquals(MorphType.EYEBROW, MorphType.decode((byte)0x01));
+        assertEquals(MorphType.EYE,     MorphType.decode((byte)0x02));
+        assertEquals(MorphType.LIP,     MorphType.decode((byte)0x03));
+        assertEquals(MorphType.EXTRA,   MorphType.decode((byte)0x04));
+        assertNull(MorphType.decode((byte)0x05));
+
+        return;
+    }
+
+    /**
+     * Test of encode method, of class MorphType.
+     */
+    @Test
+    public void testEncode(){
+        System.out.println("encode");
+
+        assertEquals(0x00, MorphType.BASE.encode());
+        assertEquals(0x01, MorphType.EYEBROW.encode());
+        assertEquals(0x02, MorphType.EYE.encode());
+        assertEquals(0x03, MorphType.LIP.encode());
+        assertEquals(0x04, MorphType.EXTRA.encode());
+
+        return;
+    }
+
+    /**
+     * Test of getGuiName method, of class MorphType.
+     */
+    @Test
+    public void testGetGuiName_0args(){
+        System.out.println("getGuiName");
+
+        Locale locale = Locale.getDefault();
+
+        for(MorphType type : MorphType.values()){
+            assertEquals(type.getGuiName(locale), type.getGuiName());
+        }
+
+        return;
+    }
+
+    /**
+     * Test of getGuiName method, of class MorphType.
+     */
+    @Test
+    public void testGetGuiName_Locale(){
+        System.out.println("getGuiName");
+
+        Locale locale = Locale.JAPANESE;
+
+        assertEquals("base", MorphType.BASE.getGuiName(locale));
+        assertEquals("まゆ", MorphType.EYEBROW.getGuiName(locale));
+        assertEquals("目", MorphType.EYE.getGuiName(locale));
+        assertEquals("リップ", MorphType.LIP.getGuiName(locale));
+        assertEquals("その他", MorphType.EXTRA.getGuiName(locale));
+        
+        return;
+    }
+
+}
index 5caead7..7bc0927 100644 (file)
-/*\r
- * sample handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package sample.pmd;\r
-\r
-import jp.sourceforge.mikutoga.parser.ParseStage;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdBasicHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdBoneHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdEngHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdJointHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdMaterialHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdMorphHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdRigidHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdShapeHandler;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdToonHandler;\r
-\r
-/**\r
- * サンプルのハンドラ。\r
- */\r
-public class DummyHandler\r
-        implements PmdBasicHandler,\r
-                   PmdBoneHandler,\r
-                   PmdShapeHandler,\r
-                   PmdMorphHandler,\r
-                   PmdMaterialHandler,\r
-                   PmdEngHandler,\r
-                   PmdToonHandler,\r
-                   PmdRigidHandler,\r
-                   PmdJointHandler {\r
-\r
-    public DummyHandler(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    public void pmdParseStart(){\r
-        System.out.println("PMD parse start");\r
-        return;\r
-    }\r
-\r
-    public void pmdParseEnd(boolean hasMoreData){\r
-        System.out.println("PMD parse end");\r
-        if(hasMoreData){\r
-            System.out.println("thre is unknown data below");\r
-        }\r
-        return;\r
-    }\r
-\r
-    public void loopStart(ParseStage stage, int loops){\r
-        System.out.println("===== Loop start ===== * " + loops);\r
-        return;\r
-    }\r
-\r
-    public void loopNext(ParseStage stage){\r
-        return;\r
-    }\r
-\r
-    public void loopEnd(ParseStage stage){\r
-        System.out.println("===== Loop end =====");\r
-        return;\r
-    }\r
-\r
-    public void pmdHeaderInfo(float ver){\r
-        System.out.println("ver=" + ver);\r
-        return;\r
-    }\r
-\r
-    public void pmdModelInfo(String modelName, String description){\r
-        System.out.println("modelName=" + modelName);\r
-        System.out.println("comment=" + description);\r
-        return;\r
-    }\r
-\r
-    public void pmdVertexPosition(float xPos, float yPos, float zPos){\r
-//        System.out.println("x,y,z = " + xPos + "," + yPos + "," + zPos);\r
-        return;\r
-    }\r
-\r
-    public void pmdVertexNormal(float xVec, float yVec, float zVec){\r
-//        System.out.println("x,y,z = " + xVec + "," + yVec + "," + zVec);\r
-    }\r
-\r
-    public void pmdVertexUV(float uVal, float vVal){\r
-        return;\r
-    }\r
-\r
-    public void pmdVertexWeight(int boneId_1, int boneId_2,\r
-                                  int weightForB1){\r
-//        System.out.println("x,y,z = "\r
-//        + boneId_1 + "," + boneId_2 + "," + weightForB1);\r
-        return;\r
-    }\r
-\r
-    public void pmdVertexEdge(boolean hideEdge){\r
-//        System.out.println("x,y,z = " + hideEdge);\r
-        return;\r
-    }\r
-\r
-    public void pmdSurfaceTriangle(int vertexId_1,\r
-                                      int vertexId_2,\r
-                                      int vertexId_3){\r
-//        System.out.println("v1,v2,v3 = "\r
-//                + vertexId_1 + "," + vertexId_2 + "," + vertexId_3);\r
-    }\r
-\r
-    public void pmdMaterialDiffuse(float red, float green, float blue,\r
-                                      float alpha ){\r
-//        System.out.println("diffuse rgba="\r
-//        + red + "," + green + "," + blue + "," + alpha);\r
-        return;\r
-    }\r
-\r
-    public void pmdMaterialSpecular(float red, float green, float blue,\r
-                                       float shininess){\r
-//        System.out.println("specular rgbs="\r
-//        + red + "," + green + "," + blue + "," + shininess);\r
-        return;\r
-    }\r
-\r
-    public void pmdMaterialAmbient(float red, float green, float blue){\r
-//        System.out.println("ambient rgb=" + red + "," + green + "," + blue);\r
-        return;\r
-    }\r
-\r
-    public void pmdMaterialShading(int toon_idx,\r
-                                      String textureFile, String sphereFile){\r
-//        System.out.println("toon idx=" + toon_idx);\r
-//        System.out.println("texfile=" + textureFile);\r
-//        System.out.println("spherefile=" + sphereFile);\r
-        return;\r
-    }\r
-\r
-    public void pmdMaterialInfo(boolean hasEdge, int surfaceNum){\r
-//        System.out.println("surfaces=" + surfaceNum);\r
-        return;\r
-    }\r
-\r
-    public void pmdBoneInfo(String boneName, byte boneKind){\r
-//        System.out.println("bonename = " + boneName);\r
-//        System.out.println("kind = " + boneKind);\r
-        return;\r
-    }\r
-\r
-    public void pmdBoneLink(int parentId, int tailId, int ikId){\r
-//        System.out.println("parent = " + parentId);\r
-//        System.out.println("tail = " + tailId);\r
-//        System.out.println("ik = " + ikId);\r
-        return;\r
-    }\r
-\r
-    public void pmdBonePosition(float xPos, float yPos, float zPos){\r
-//        System.out.println("x="+xPos+" y="+yPos+" z="+zPos);\r
-        return;\r
-    }\r
-\r
-    public void pmdIKInfo(int boneId, int targetId,\r
-                           int depth, float weight ){\r
-        return;\r
-    }\r
-\r
-    public void pmdIKChainInfo(int childId){\r
-//        System.out.println("chained bone = " + childId);\r
-        return;\r
-    }\r
-\r
-    public void pmdMorphInfo(String morphName, byte morphType){\r
-//        System.out.println("morph name = " + morphName);\r
-        return;\r
-    }\r
-\r
-    public void pmdMorphVertexInfo(int vertexId,\r
-                                 float xPos, float yPos, float zPos){\r
-//        System.out.println("id="+vertexId+",x="+xPos+",y="+yPos+",z="+zPos);\r
-        return;\r
-    }\r
-\r
-    public void pmdMorphOrderInfo(int morphId){\r
-//        System.out.println("morph idx = " + morphId);\r
-        return;\r
-    }\r
-\r
-    public void pmdBoneGroupInfo(String groupName){\r
-//        System.out.println("group name = " + groupName);\r
-        return;\r
-    }\r
-\r
-    public void pmdGroupedBoneInfo(int boneId, int groupId){\r
-//        System.out.println("bone index="\r
-//        + boneId + " groupIndex=" + groupId);\r
-        return;\r
-    }\r
-\r
-    public void pmdEngEnabled(boolean hasEnglishInfo){\r
-        return;\r
-    }\r
-\r
-    public void pmdEngModelInfo(String modelName, String description){\r
-        return;\r
-    }\r
-\r
-    public void pmdEngBoneInfo(String boneName){\r
-//        System.out.println("bone eng name = " + boneName);\r
-        return;\r
-    }\r
-\r
-    public void pmdEngMorphInfo(String morphName){\r
-//        System.out.println("morph eng name = " + morphName);\r
-        return;\r
-    }\r
-\r
-    public void pmdEngBoneGroupInfo(String groupName){\r
-//        System.out.println("group eng name = " + groupName);\r
-        return;\r
-    }\r
-\r
-    public void pmdToonFileInfo(String toonName){\r
-//        System.out.println("toon file name = " + toonName);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidName(String rigidName){\r
-//        System.out.println("rigid name = " + rigidName);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidInfo(int rigidGroupId, int linkedBoneId){\r
-//        System.out.println("rigid group = "\r
-//        + rigidGroupId + ",linked Bone =" + linkedBoneId);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidShape(byte shapeType,\r
-                                float width, float height, float depth){\r
-//        System.out.println("type="+shapeType);\r
-//        System.out.println("w="+width);\r
-//        System.out.println("h="+height);\r
-//        System.out.println("d="+depth);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidPosition(float posX, float posY, float posZ){\r
-//        System.out.println("x="+posX);\r
-//        System.out.println("y="+posY);\r
-//        System.out.println("z="+posZ);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidRotation(float rotX, float rotY, float rotZ){\r
-//        System.out.println("x="+rotX);\r
-//        System.out.println("y="+rotY);\r
-//        System.out.println("z="+rotZ);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidPhysics(float mass,\r
-                                  float fadePos, float fadeRot,\r
-                                  float restitution, float friction ){\r
-//        System.out.println("mass="+mass);\r
-//        System.out.println("fadePos="+fadePos);\r
-//        System.out.println("fadeRot="+fadeRot);\r
-//        System.out.println("recoil="+restitution);\r
-//        System.out.println("friction="+friction);\r
-        return;\r
-    }\r
-\r
-    public void pmdRigidBehavior(byte behaveType, short collisionMap){\r
-//      System.out.println("type="+behaveType);\r
-//        System.out.println("map="+collisionMap);\r
-        return;\r
-    }\r
-\r
-    public void pmdJointName(String jointName){\r
-//        System.out.println("joint name = " + jointName);\r
-        return;\r
-    }\r
-\r
-    public void pmdJointLink(int rigidId_A, int rigidId_B){\r
-//        System.out.println("rigid1 = " + rigidId_A+",rigidB = " + rigidId_B);\r
-        return;\r
-    }\r
-\r
-    public void pmdJointPosition(float posX, float posY, float posZ){\r
-//        System.out.println("posX = " + posX);\r
-//        System.out.println("posY = " + posY);\r
-//        System.out.println("posZ = " + posZ);\r
-        return;\r
-    }\r
-\r
-    public void pmdJointRotation(float rotX, float rotY, float rotZ){\r
-//        System.out.println("rotX = " + rotX);\r
-//        System.out.println("rotY = " + rotY);\r
-//        System.out.println("rotZ = " + rotZ);\r
-        return;\r
-    }\r
-\r
-    public void pmdPositionLimit(float posX_lim1, float posX_lim2,\r
-                                   float posY_lim1, float posY_lim2,\r
-                                   float posZ_lim1, float posZ_lim2 ){\r
-//        System.out.println("limX = " + posX_lim1+"-"+posX_lim2);\r
-//        System.out.println("limY = " + posY_lim1+"-"+posY_lim2);\r
-//        System.out.println("limZ = " + posZ_lim1+"-"+posZ_lim2);\r
-        return;\r
-    }\r
-\r
-    public void pmdRotationLimit(float rotX_lim1, float rotX_lim2,\r
-                                   float rotY_lim1, float rotY_lim2,\r
-                                   float rotZ_lim1, float rotZ_lim2 ){\r
-//        System.out.println("limX = " + rotX_lim1+"-"+rotX_lim2);\r
-//        System.out.println("limY = " + rotY_lim1+"-"+rotY_lim2);\r
-//        System.out.println("limZ = " + rotZ_lim1+"-"+rotZ_lim2);\r
-        return;\r
-    }\r
-\r
-    public void pmdElasticPosition(float elasticPosX,\r
-                                  float elasticPosY,\r
-                                  float elasticPosZ ){\r
-//        System.out.println("posX="+elasticPosX);\r
-//        System.out.println("posY="+elasticPosY);\r
-//        System.out.println("posZ="+elasticPosZ);\r
-        return;\r
-    }\r
-\r
-    public void pmdElasticRotation(float elasticRotX,\r
-                                  float elasticRotY,\r
-                                  float elasticRotZ ){\r
-//        System.out.println("posX="+elasticRotX);\r
-//        System.out.println("posY="+elasticRotY);\r
-//        System.out.println("posZ="+elasticRotZ);\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * sample handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package sample.pmd;
+
+import jp.sourceforge.mikutoga.parser.ParseStage;
+import jp.sourceforge.mikutoga.parser.pmd.PmdBasicHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdBoneHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdEngHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdJointHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdMaterialHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdMorphHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdRigidHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdShapeHandler;
+import jp.sourceforge.mikutoga.parser.pmd.PmdToonHandler;
+
+/**
+ * サンプルのハンドラ。
+ */
+public class DummyHandler
+        implements PmdBasicHandler,
+                   PmdBoneHandler,
+                   PmdShapeHandler,
+                   PmdMorphHandler,
+                   PmdMaterialHandler,
+                   PmdEngHandler,
+                   PmdToonHandler,
+                   PmdRigidHandler,
+                   PmdJointHandler {
+
+    public DummyHandler(){
+        super();
+        return;
+    }
+
+    public void pmdParseStart(){
+        System.out.println("PMD parse start");
+        return;
+    }
+
+    public void pmdParseEnd(boolean hasMoreData){
+        System.out.println("PMD parse end");
+        if(hasMoreData){
+            System.out.println("thre is unknown data below");
+        }
+        return;
+    }
+
+    public void loopStart(ParseStage stage, int loops){
+        System.out.println("===== Loop start ===== * " + loops);
+        return;
+    }
+
+    public void loopNext(ParseStage stage){
+        return;
+    }
+
+    public void loopEnd(ParseStage stage){
+        System.out.println("===== Loop end =====");
+        return;
+    }
+
+    public void pmdHeaderInfo(float ver){
+        System.out.println("ver=" + ver);
+        return;
+    }
+
+    public void pmdModelInfo(String modelName, String description){
+        System.out.println("modelName=" + modelName);
+        System.out.println("comment=" + description);
+        return;
+    }
+
+    public void pmdVertexPosition(float xPos, float yPos, float zPos){
+//        System.out.println("x,y,z = " + xPos + "," + yPos + "," + zPos);
+        return;
+    }
+
+    public void pmdVertexNormal(float xVec, float yVec, float zVec){
+//        System.out.println("x,y,z = " + xVec + "," + yVec + "," + zVec);
+    }
+
+    public void pmdVertexUV(float uVal, float vVal){
+        return;
+    }
+
+    public void pmdVertexWeight(int boneId_1, int boneId_2,
+                                  int weightForB1){
+//        System.out.println("x,y,z = "
+//        + boneId_1 + "," + boneId_2 + "," + weightForB1);
+        return;
+    }
+
+    public void pmdVertexEdge(boolean hideEdge){
+//        System.out.println("x,y,z = " + hideEdge);
+        return;
+    }
+
+    public void pmdSurfaceTriangle(int vertexId_1,
+                                      int vertexId_2,
+                                      int vertexId_3){
+//        System.out.println("v1,v2,v3 = "
+//                + vertexId_1 + "," + vertexId_2 + "," + vertexId_3);
+    }
+
+    public void pmdMaterialDiffuse(float red, float green, float blue,
+                                      float alpha ){
+//        System.out.println("diffuse rgba="
+//        + red + "," + green + "," + blue + "," + alpha);
+        return;
+    }
+
+    public void pmdMaterialSpecular(float red, float green, float blue,
+                                       float shininess){
+//        System.out.println("specular rgbs="
+//        + red + "," + green + "," + blue + "," + shininess);
+        return;
+    }
+
+    public void pmdMaterialAmbient(float red, float green, float blue){
+//        System.out.println("ambient rgb=" + red + "," + green + "," + blue);
+        return;
+    }
+
+    public void pmdMaterialShading(int toon_idx,
+                                      String textureFile, String sphereFile){
+//        System.out.println("toon idx=" + toon_idx);
+//        System.out.println("texfile=" + textureFile);
+//        System.out.println("spherefile=" + sphereFile);
+        return;
+    }
+
+    public void pmdMaterialInfo(boolean hasEdge, int surfaceNum){
+//        System.out.println("surfaces=" + surfaceNum);
+        return;
+    }
+
+    public void pmdBoneInfo(String boneName, byte boneKind){
+//        System.out.println("bonename = " + boneName);
+//        System.out.println("kind = " + boneKind);
+        return;
+    }
+
+    public void pmdBoneLink(int parentId, int tailId, int ikId){
+//        System.out.println("parent = " + parentId);
+//        System.out.println("tail = " + tailId);
+//        System.out.println("ik = " + ikId);
+        return;
+    }
+
+    public void pmdBonePosition(float xPos, float yPos, float zPos){
+//        System.out.println("x="+xPos+" y="+yPos+" z="+zPos);
+        return;
+    }
+
+    public void pmdIKInfo(int boneId, int targetId,
+                           int depth, float weight ){
+        return;
+    }
+
+    public void pmdIKChainInfo(int childId){
+//        System.out.println("chained bone = " + childId);
+        return;
+    }
+
+    public void pmdMorphInfo(String morphName, byte morphType){
+//        System.out.println("morph name = " + morphName);
+        return;
+    }
+
+    public void pmdMorphVertexInfo(int vertexId,
+                                 float xPos, float yPos, float zPos){
+//        System.out.println("id="+vertexId+",x="+xPos+",y="+yPos+",z="+zPos);
+        return;
+    }
+
+    public void pmdMorphOrderInfo(int morphId){
+//        System.out.println("morph idx = " + morphId);
+        return;
+    }
+
+    public void pmdBoneGroupInfo(String groupName){
+//        System.out.println("group name = " + groupName);
+        return;
+    }
+
+    public void pmdGroupedBoneInfo(int boneId, int groupId){
+//        System.out.println("bone index="
+//        + boneId + " groupIndex=" + groupId);
+        return;
+    }
+
+    public void pmdEngEnabled(boolean hasEnglishInfo){
+        return;
+    }
+
+    public void pmdEngModelInfo(String modelName, String description){
+        return;
+    }
+
+    public void pmdEngBoneInfo(String boneName){
+//        System.out.println("bone eng name = " + boneName);
+        return;
+    }
+
+    public void pmdEngMorphInfo(String morphName){
+//        System.out.println("morph eng name = " + morphName);
+        return;
+    }
+
+    public void pmdEngBoneGroupInfo(String groupName){
+//        System.out.println("group eng name = " + groupName);
+        return;
+    }
+
+    public void pmdToonFileInfo(String toonName){
+//        System.out.println("toon file name = " + toonName);
+        return;
+    }
+
+    public void pmdRigidName(String rigidName){
+//        System.out.println("rigid name = " + rigidName);
+        return;
+    }
+
+    public void pmdRigidInfo(int rigidGroupId, int linkedBoneId){
+//        System.out.println("rigid group = "
+//        + rigidGroupId + ",linked Bone =" + linkedBoneId);
+        return;
+    }
+
+    public void pmdRigidShape(byte shapeType,
+                                float width, float height, float depth){
+//        System.out.println("type="+shapeType);
+//        System.out.println("w="+width);
+//        System.out.println("h="+height);
+//        System.out.println("d="+depth);
+        return;
+    }
+
+    public void pmdRigidPosition(float posX, float posY, float posZ){
+//        System.out.println("x="+posX);
+//        System.out.println("y="+posY);
+//        System.out.println("z="+posZ);
+        return;
+    }
+
+    public void pmdRigidRotation(float rotX, float rotY, float rotZ){
+//        System.out.println("x="+rotX);
+//        System.out.println("y="+rotY);
+//        System.out.println("z="+rotZ);
+        return;
+    }
+
+    public void pmdRigidPhysics(float mass,
+                                  float fadePos, float fadeRot,
+                                  float restitution, float friction ){
+//        System.out.println("mass="+mass);
+//        System.out.println("fadePos="+fadePos);
+//        System.out.println("fadeRot="+fadeRot);
+//        System.out.println("recoil="+restitution);
+//        System.out.println("friction="+friction);
+        return;
+    }
+
+    public void pmdRigidBehavior(byte behaveType, short collisionMap){
+//      System.out.println("type="+behaveType);
+//        System.out.println("map="+collisionMap);
+        return;
+    }
+
+    public void pmdJointName(String jointName){
+//        System.out.println("joint name = " + jointName);
+        return;
+    }
+
+    public void pmdJointLink(int rigidId_A, int rigidId_B){
+//        System.out.println("rigid1 = " + rigidId_A+",rigidB = " + rigidId_B);
+        return;
+    }
+
+    public void pmdJointPosition(float posX, float posY, float posZ){
+//        System.out.println("posX = " + posX);
+//        System.out.println("posY = " + posY);
+//        System.out.println("posZ = " + posZ);
+        return;
+    }
+
+    public void pmdJointRotation(float rotX, float rotY, float rotZ){
+//        System.out.println("rotX = " + rotX);
+//        System.out.println("rotY = " + rotY);
+//        System.out.println("rotZ = " + rotZ);
+        return;
+    }
+
+    public void pmdPositionLimit(float posX_lim1, float posX_lim2,
+                                   float posY_lim1, float posY_lim2,
+                                   float posZ_lim1, float posZ_lim2 ){
+//        System.out.println("limX = " + posX_lim1+"-"+posX_lim2);
+//        System.out.println("limY = " + posY_lim1+"-"+posY_lim2);
+//        System.out.println("limZ = " + posZ_lim1+"-"+posZ_lim2);
+        return;
+    }
+
+    public void pmdRotationLimit(float rotX_lim1, float rotX_lim2,
+                                   float rotY_lim1, float rotY_lim2,
+                                   float rotZ_lim1, float rotZ_lim2 ){
+//        System.out.println("limX = " + rotX_lim1+"-"+rotX_lim2);
+//        System.out.println("limY = " + rotY_lim1+"-"+rotY_lim2);
+//        System.out.println("limZ = " + rotZ_lim1+"-"+rotZ_lim2);
+        return;
+    }
+
+    public void pmdElasticPosition(float elasticPosX,
+                                  float elasticPosY,
+                                  float elasticPosZ ){
+//        System.out.println("posX="+elasticPosX);
+//        System.out.println("posY="+elasticPosY);
+//        System.out.println("posZ="+elasticPosZ);
+        return;
+    }
+
+    public void pmdElasticRotation(float elasticRotX,
+                                  float elasticRotY,
+                                  float elasticRotZ ){
+//        System.out.println("posX="+elasticRotX);
+//        System.out.println("posY="+elasticRotY);
+//        System.out.println("posZ="+elasticRotZ);
+        return;
+    }
+
+}
index ed4d624..8fdfec4 100644 (file)
-/*\r
- * sample parser\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2010 MikuToga Partners\r
- */\r
-\r
-package sample.pmd;\r
-\r
-import java.io.BufferedInputStream;\r
-import java.io.File;\r
-import java.io.FileInputStream;\r
-import java.io.FileNotFoundException;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import jp.sourceforge.mikutoga.parser.MmdFormatException;\r
-import jp.sourceforge.mikutoga.parser.MmdSource;\r
-import jp.sourceforge.mikutoga.parser.pmd.PmdParser;\r
-\r
-/**\r
- * パーサ利用のサンプルプログラム。\r
- */\r
-public class DummyMain {\r
-\r
-    private static final String PMDFILE;\r
-    private static final int BUF_SZ = 4086;\r
-    private static final DummyHandler handler = new DummyHandler();\r
-\r
-    static{\r
-        PMDFILE = "D:\\Test\\test.pmd";\r
-    }\r
-\r
-    /**\r
-     * 入力ソースを準備する。\r
-     * @param fname ファイル名\r
-     * @return 入力ソース\r
-     */\r
-    private static MmdSource buildSource(String fname){\r
-        File file = new File(fname);\r
-\r
-        InputStream is;\r
-        try{\r
-            is = new FileInputStream(file);\r
-        }catch(FileNotFoundException e){\r
-            System.err.println(e);\r
-            System.exit(1);\r
-            return null;\r
-        }\r
-        is = new BufferedInputStream(is, BUF_SZ);\r
-\r
-        MmdSource source = new MmdSource(is);\r
-\r
-        return source;\r
-    }\r
-\r
-    /**\r
-     * 各種ハンドラをパーサにセットアップする。\r
-     * @param parser パーサ\r
-     */\r
-    private static void setupHandler(PmdParser parser){\r
-        parser.setBasicHandler(handler);\r
-        parser.setShapeHandler(handler);\r
-        parser.setMaterialHandler(handler);\r
-        parser.setBoneHandler(handler);\r
-        parser.setMorphHandler(handler);\r
-        parser.setEngHandler(handler);\r
-        parser.setToonHandler(handler);\r
-        parser.setRigidHandler(handler);\r
-        parser.setJointHandler(handler);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Java実行エントリ\r
-     * @param args 起動引数\r
-     */\r
-    public static void main(String[] args){\r
-        String fname;\r
-        if(args.length == 1) fname = args[0];\r
-        else                 fname = PMDFILE;\r
-\r
-        MmdSource source = buildSource(fname);\r
-\r
-        PmdParser parser = new PmdParser(source);\r
-\r
-        setupHandler(parser);\r
-\r
-        try{\r
-            parser.parsePmd();\r
-        }catch(IOException e){\r
-            System.err.println(e);\r
-            System.exit(1);\r
-        }catch(MmdFormatException e){\r
-            System.err.println(e);\r
-            System.exit(1);\r
-        }\r
-\r
-        System.exit(0);\r
-\r
-        return;\r
-    }\r
-\r
-}\r
+/*
+ * sample parser
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package sample.pmd;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.parser.MmdSource;
+import jp.sourceforge.mikutoga.parser.pmd.PmdParser;
+
+/**
+ * パーサ利用のサンプルプログラム。
+ */
+public class DummyMain {
+
+    private static final String PMDFILE;
+    private static final int BUF_SZ = 4086;
+    private static final DummyHandler handler = new DummyHandler();
+
+    static{
+        PMDFILE = "D:\\Test\\test.pmd";
+    }
+
+    /**
+     * 入力ソースを準備する。
+     * @param fname ファイル名
+     * @return 入力ソース
+     */
+    private static MmdSource buildSource(String fname){
+        File file = new File(fname);
+
+        InputStream is;
+        try{
+            is = new FileInputStream(file);
+        }catch(FileNotFoundException e){
+            System.err.println(e);
+            System.exit(1);
+            return null;
+        }
+        is = new BufferedInputStream(is, BUF_SZ);
+
+        MmdSource source = new MmdSource(is);
+
+        return source;
+    }
+
+    /**
+     * 各種ハンドラをパーサにセットアップする。
+     * @param parser パーサ
+     */
+    private static void setupHandler(PmdParser parser){
+        parser.setBasicHandler(handler);
+        parser.setShapeHandler(handler);
+        parser.setMaterialHandler(handler);
+        parser.setBoneHandler(handler);
+        parser.setMorphHandler(handler);
+        parser.setEngHandler(handler);
+        parser.setToonHandler(handler);
+        parser.setRigidHandler(handler);
+        parser.setJointHandler(handler);
+
+        return;
+    }
+
+    /**
+     * Java実行エントリ
+     * @param args 起動引数
+     */
+    public static void main(String[] args){
+        String fname;
+        if(args.length == 1) fname = args[0];
+        else                 fname = PMDFILE;
+
+        MmdSource source = buildSource(fname);
+
+        PmdParser parser = new PmdParser(source);
+
+        setupHandler(parser);
+
+        try{
+            parser.parsePmd();
+        }catch(IOException e){
+            System.err.println(e);
+            System.exit(1);
+        }catch(MmdFormatException e){
+            System.err.println(e);
+            System.exit(1);
+        }
+
+        System.exit(0);
+
+        return;
+    }
+
+}