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
+^nbactions\.xml$\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
-    "-//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用チェック項目定義。
 
-    Checkstyle5.1以降向けに記述。
+    Checkstyle 5.0 以降向けに記述。
 
     [ http://checkstyle.sourceforge.net/ ]
 
 <module name="Checker">
 
     <property name="charset" value="UTF-8" />
+    <property name="localeCountry" value="JP" />
+    <property name="localeLanguage" value="ja" />
     <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" />
     <module name="FileTabCharacter" />
 
 
-<!-- Filters
-    <module name="SeverityMatchFilter" />
-    <module name="SuppressionFilter" />
-    <module name="SuppressionCommentFilter" />
-    <module name="SuppressWithNearbyCommentFilter" />
--->
-
-
     <module name="TreeWalker">
 
-        <property name="tabWidth" value="4" />
+        <module name="FileContentsHolder" />
 
 
     <!-- Annotations -->
 <!--    <module name="DesignForExtension" />  -->
         <module name="MutableException" />
         <module name="ThrowsCount">
-            <property name="max" value="4" />
+            <property name="max" value="3" />
         </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="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 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="UpperEll" />
         <module name="ArrayTypeStyle" />
 <!--    <module name="FinalParameters" />  -->
-        <module name="DescendantToken" />
+<!--    <module name="DescendantToken" />  -->
 <!--
         <module name="Indentation">
-            <property name="basicOffset" value="4" />
             <property name="caseIndent" value="0" />
         </module>
 -->
             <property name="duplicateLimit" value="1" />
         </module>
 
+
     <!-- Modifiers -->
 
         <module name="ModifierOrder" />
 
     <!-- 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="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="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="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">
                        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,
                        "
             />
 <!-- バグ?
         <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>
+
 </module>
 
 <!-- EOF -->
index 1b5fcf2..ad3dba9 100644 (file)
@@ -9,12 +9,12 @@
 -->
 
 <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"
+  name="Custom ruleset"
 >
 
     <rule ref="rulesets/basic.xml">
     <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">
-        <exclude name="DataflowAnomalyAnalysis" />
+        <exclude name="NullAssignment" />
         <exclude name="OnlyOneReturn" />
         <exclude name="DefaultPackage" />
+        <exclude name="DataflowAnomalyAnalysis" />
     </rule>
 
     <rule ref="rulesets/coupling.xml" />
 
     <rule ref="rulesets/design.xml">
+        <exclude name="ConfusingTernary" />
         <exclude name="UnnecessaryLocalBeforeReturn" />
     </rule>
 
     <rule ref="rulesets/migrating_to_15.xml" />
 
     <rule ref="rulesets/naming.xml">
-        <exclude name="LongVariable" />
         <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">
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カプセルの高さ
+&nbs