・ジンバルロック判定を甘くした。
・多言語対応に際してデフォルトロケールへのフォールバックを禁止。
・コールバックpmdIKInfo()がpmdIKChainInfo()より先に呼ばれるよう変更。
+ ・MikuMikuDance Ver7.40以降の新VMDファイルフォーマットに対応
2.102.2 (2013-03-17)
・Maven3対応。
<groupId>jp.sourceforge.mikutoga</groupId>
<artifactId>togagem</artifactId>
- <version>2.102.5-SNAPSHOT</version>
+ <version>2.102.7-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TogaGem</name>
*/
public static final int MORPHNAME_MAX = 15;
+ /**
+ * IK ON/OFFスイッチ用ボーン名最大長。バイト単位。
+ * <p>※MikuMikuDance Ver7.40からの機能。
+ * <p>モーション指定用ボーン名と長さが違うので注意。
+ */
+ public static final int IKSWBONENAME_MAX = 20;
+
/**
* 隠しコンストラクタ。
--- /dev/null
+/*
+ * VMD boolean info handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.vmd.parser;
+
+import jp.sfjp.mikutoga.bin.parser.LoopHandler;
+import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.ParseStage;
+
+/**
+ * VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効)
+ * の通知用ハンドラ。
+ * <p>MikuMikuDance Ver7.40よりVMDファイルに導入された新仕様。
+ */
+public interface VmdBoolHandler extends LoopHandler {
+
+ /** モデル表示スイッチ抽出ループ識別子。 */
+ ParseStage MODELSIGHT_LIST = new ParseStage();
+
+ /** IK有効スイッチ抽出ループ識別子。 */
+ ParseStage IKSW_LIST = new ParseStage();
+
+
+ /**
+ * モデルの表示フラグを通知する。
+ * <p>{@link #MODELSIGHT_LIST}ループの構成要素。
+ * @param show モデルの表示が行われる場合true
+ * @param keyFrameNo キーフレーム番号
+ * @throws MmdFormatException 不正フォーマットによる
+ * パース処理の中断をパーサに指示
+ */
+ void vmdModelSight(boolean show, int keyFrameNo)
+ throws MmdFormatException;
+
+ /**
+ * IKボーン別のIK処理のON/OFFを通知する。
+ * <p>{@link #MODELSIGHT_LIST}ループの下位
+ * {@link #IKSW_LIST}ループの構成要素。
+ * @param boneName IKボーン名
+ * @param validIk IK処理が無効になる場合false
+ * @param keyFrameNo キーフレーム番号
+ * @throws MmdFormatException 不正フォーマットによる
+ * パース処理の中断をパーサに指示
+ */
+ void vmdIkSwitch(String boneName, boolean validIk, int keyFrameNo)
+ throws MmdFormatException;
+
+}
--- /dev/null
+/*
+ * VMD boolean data parser
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.vmd.parser;
+
+import java.io.IOException;
+import jp.sfjp.mikutoga.bin.parser.BinParser;
+import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.ProxyParser;
+import jp.sfjp.mikutoga.bin.parser.TextDecoder;
+import jp.sfjp.mikutoga.vmd.VmdConst;
+
+/**
+ * VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効)
+ * パーサ。
+ * <p>MikuMikuDance Ver7.40以降でサポート
+ */
+class VmdBoolParser extends ProxyParser {
+
+ private final TextDecoder decoderWin31j =
+ new TextDecoder(VmdBasicParser.CS_WIN31J);
+
+ private VmdBoolHandler handler = VmdUnifiedHandler.EMPTY;
+
+
+ /**
+ * コンストラクタ。
+ * @param parser 委譲先パーサ
+ */
+ VmdBoolParser(BinParser parser){
+ super(parser);
+ this.decoderWin31j.setZeroChopMode(true);
+ return;
+ }
+
+
+ /**
+ * ON/OFF情報通知用ハンドラを登録する。
+ * @param boolHandler ハンドラ
+ */
+ void setBoolHandler(VmdBoolHandler boolHandler){
+ if(boolHandler == null){
+ this.handler = VmdUnifiedHandler.EMPTY;
+ }else{
+ this.handler = boolHandler;
+ }
+
+ return;
+ }
+
+ /**
+ * データのパースと通知。
+ * @throws IOException IOエラー
+ * @throws MmdFormatException フォーマットエラー
+ */
+ void parse() throws IOException, MmdFormatException {
+ if( ! hasMore() ) return;
+
+ parseVmdModelSight();
+
+ return;
+ }
+
+ /**
+ * モデル表示フラグデータのパースと通知。
+ * @throws IOException IOエラー
+ * @throws MmdFormatException フォーマットエラー
+ */
+ private void parseVmdModelSight()
+ throws IOException, MmdFormatException{
+ int modelSightNo = parseLeInt();
+
+ this.handler.loopStart(VmdBoolHandler.MODELSIGHT_LIST,
+ modelSightNo );
+
+ for(int ct = 0; ct < modelSightNo; ct++){
+ int keyFrameNo = parseLeInt();
+ boolean show = parseBoolean();
+ this.handler.vmdModelSight(show, keyFrameNo);
+
+ parseVmdIkSwitch(keyFrameNo);
+
+ this.handler.loopNext(VmdBoolHandler.MODELSIGHT_LIST);
+ }
+
+ this.handler.loopEnd(VmdBoolHandler.MODELSIGHT_LIST);
+
+ return;
+ }
+
+ /**
+ * IK有効スイッチデータのパースと通知。
+ * @param keyFrameNo キーフレーム番号
+ * @throws IOException IOエラー
+ * @throws MmdFormatException フォーマットエラー
+ */
+ private void parseVmdIkSwitch(int keyFrameNo)
+ throws IOException, MmdFormatException{
+ int ikSwitchNo = parseLeInt();
+
+ this.handler.loopStart(VmdBoolHandler.IKSW_LIST, ikSwitchNo);
+
+ for(int ct = 0; ct < ikSwitchNo; ct++){
+ String boneName = parseString(this.decoderWin31j,
+ VmdConst.IKSWBONENAME_MAX );
+ boolean valid = parseBoolean();
+ this.handler.vmdIkSwitch(boneName, valid, keyFrameNo);
+
+ this.handler.loopNext(VmdBoolHandler.IKSW_LIST);
+ }
+
+ this.handler.loopEnd(VmdBoolHandler.IKSW_LIST);
+
+ return;
+ }
+
+}
private final VmdBasicParser basicParser;
private final VmdCameraParser cameraParser;
private final VmdLightingParser lightingParser;
+ private final VmdBoolParser boolParser;
private VmdBasicHandler basicHandler = VmdUnifiedHandler.EMPTY;
- private boolean ignoreName = true;
private boolean redundantCheck = false;
this.basicParser = new VmdBasicParser(parser);
this.cameraParser = new VmdCameraParser(parser);
this.lightingParser = new VmdLightingParser(parser);
+ this.boolParser = new VmdBoolParser(parser);
return;
}
}
/**
- * カメラ・ライティングデータのパースを試みるか否かの判断で、
- * 特殊モデル名判定を無視するか否か設定する。
- * デフォルトではモデル名を無視。
- * <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、
- * オフにするとパースに成功する場合がある。
- * @param mode モデル名を無視するならtrue
+ * ON/OFF情報通知用ハンドラを登録する。
+ * @param boolHandler ハンドラ
*/
- public void setIgnoreName(boolean mode){
- this.ignoreName = mode;
+ public void setBoolHandler(VmdBoolHandler boolHandler){
+ this.boolParser.setBoolHandler(boolHandler);
return;
}
* デフォルトではチェックを行わない。
* <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、
* オフにするとパースに成功する場合がある。
+ * <p>※MMD Ver7.39x64以降はチェック回避必須。
* @param mode チェックさせたければtrue
*/
public void setRedundantCheck(boolean mode){
* @throws MmdFormatException フォーマットエラー
*/
public void parseVmd() throws IOException, MmdFormatException {
- setIgnoreName(this.ignoreName);
setRedundantCheck(this.redundantCheck);
this.basicHandler.vmdParseStart();
/**
* VMDファイル本体のパースを開始する。
- * <p>モデル名がボーンモーション用と推測され、
- * かつパーサがStrict-modeでない場合、
- * カメラ、ライティングデータのパースは行われない。
* @throws IOException IOエラー
* @throws MmdFormatException フォーマットエラー
*/
private void parseBody() throws IOException, MmdFormatException{
this.basicParser.parse();
- if(this.basicParser.hasStageActName() || this.ignoreName){
+ if(this.cameraParser.hasMore()){
this.cameraParser.parse();
this.lightingParser.parse();
}
+ if(this.boolParser.hasMore()){
+ this.boolParser.parse();
+ }
+
return;
}
public interface VmdUnifiedHandler
extends VmdBasicHandler,
VmdCameraHandler,
- VmdLightingHandler {
+ VmdLightingHandler,
+ VmdBoolHandler {
/** 何もしない統合ハンドラ。 */
VmdUnifiedHandler EMPTY =
* Copyright(c) 2013 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.IOException;
import java.util.regex.Matcher;
* Copyright(c) 2010 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.Closeable;
import java.io.Flushable;
* Copyright(c) 2010 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
* Copyright(c) 2011 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.text.MessageFormat;
import java.util.Iterator;
* Copyright(c) 2010 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.util.Iterator;
import java.util.LinkedList;
* Copyright(c) 2013 olyutorskii
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.net.URI;
* Copyright(c) 2013 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.IOException;
--- /dev/null
+/*
+ * Sax 2 Xsd-types converter
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.xml;
+
+import javax.xml.bind.DatatypeConverter;
+import org.xml.sax.Attributes;
+
+/**
+ * XSD各種型のSAX属性値をJavaプリミティブ型へ変換する。
+ */
+public final class SaxAttr {
+
+ /**
+ * 隠しコンストラクタ。
+ */
+ private SaxAttr(){
+ assert false;
+ throw new AssertionError();
+ }
+
+
+ /**
+ * 属性名に対応する属性値があるか否か判定する。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性名に対応する属性値がある場合はtrue
+ */
+ public static boolean hasAttr(Attributes attr, String name){
+ if(attr.getValue(name) == null) return false;
+ return true;
+ }
+
+ /**
+ * xsd:string型属性値の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性値。該当する属性が無ければnull。
+ */
+ public static String getStringAttr(Attributes attr, String name){
+ String attrVal = attr.getValue(name);
+ return attrVal;
+ }
+
+ /**
+ * xsd:boolean型属性値の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性値。
+ * @throws IllegalArgumentException boolean型表記ではない
+ */
+ public static boolean getBooleanAttr(Attributes attr, String name)
+ throws IllegalArgumentException{
+ String attrVal = attr.getValue(name);
+ boolean bVal;
+ bVal = DatatypeConverter.parseBoolean(attrVal);
+ return bVal;
+ }
+
+ /**
+ * xsd:boolean型属性値の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @param def 属性が無い場合のデフォルト値
+ * @return 属性値。
+ * @throws IllegalArgumentException boolean型表記ではない
+ */
+ public static boolean getBooleanAttr(Attributes attr,
+ String name,
+ boolean def )
+ throws IllegalArgumentException{
+ String attrVal = attr.getValue(name);
+ if(attrVal == null) return def;
+
+ boolean bVal;
+ bVal = DatatypeConverter.parseBoolean(attrVal);
+
+ return bVal;
+ }
+
+ /**
+ * xsd:byte型属性の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性値。
+ * @throws NumberFormatException byte型表記ではない
+ */
+ public static byte getByteAttr(Attributes attr, String name)
+ throws NumberFormatException{
+ String attrVal = attr.getValue(name);
+ byte bVal;
+ bVal = DatatypeConverter.parseByte(attrVal);
+ return bVal;
+ }
+
+ /**
+ * xsd:float型属性値の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性値。
+ * @throws NumberFormatException float型表記ではない
+ */
+ public static float getFloatAttr(Attributes attr, String name)
+ throws NumberFormatException {
+ String attrVal = attr.getValue(name);
+ float fVal;
+ fVal = DatatypeConverter.parseFloat(attrVal);
+ return fVal;
+ }
+
+ /**
+ * xsd:int型属性値の読み込み。
+ * @param attr 属性群
+ * @param name 属性名
+ * @return 属性値。
+ * @throws NumberFormatException int型表記ではない
+ */
+ public static int getIntAttr(Attributes attr, String name)
+ throws NumberFormatException {
+ String attrVal = attr.getValue(name);
+ int iVal;
+ iVal = DatatypeConverter.parseInt(attrVal);
+ return iVal;
+ }
+
+}
* Copyright(c) 2013 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.BufferedInputStream;
import java.io.IOException;
* Copyright(c) 2011 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.util.Iterator;
import java.util.NoSuchElementException;
* Copyright(c) 2010 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
/**
* 意図しないXML文書を検出した際の例外。
* Copyright(c) 2013 MikuToga Partners
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.Closeable;
import java.io.Flushable;
* Copyright(c) 2009 olyutorskii
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
import java.io.IOException;
import java.io.InputStream;
* MikuToga XML共通ライブラリ。
*/
-package jp.sourceforge.mikutoga.xml;
+package jp.sfjp.mikutoga.xml;
/* EOF */
return;
}
+ @Override
+ public void vmdModelSight(boolean show, int keyFrameNo){
+ println("modelSight : frame#=" + keyFrameNo + " show=" + show);
+ return;
+ }
+
+ @Override
+ public void vmdIkSwitch(String boneName,
+ boolean validIk,
+ int keyFrameNo ){
+ println("IKSwitch : frame#=" + keyFrameNo + " bone=" + boneName + " valid=" + validIk);
+ return;
+ }
+
private void println(String msg){
System.out.println(msg);
return;
private static final DummyHandler handler = new DummyHandler();
static{
-// VMDFILE = "D:\\Test\\test.vmd";
- VMDFILE = "D:\\Test\\camera.vmd";
+ VMDFILE = "D:\\Test\\test.vmd";
+// VMDFILE = "D:\\Test\\camera.vmd";
}
private static InputStream buildSource(String fname){
parser.setBasicHandler(handler);
parser.setLightingHandler(handler);
parser.setCameraHandler(handler);
+ parser.setBoolHandler(handler);
return;
}
VmdParser parser = new VmdParser(source);
setupHandler(parser);
- parser.setIgnoreName(true);
parser.setRedundantCheck(false);
try{