OSDN Git Service

SAX対応
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd / model / xml / ExporterDynamics.java
1 /*
2  * dynamics xml exporter
3  *
4  * License : The MIT License
5  * Copyright(c) 2013 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.pmd.model.xml;
9
10 import java.io.IOException;
11 import java.util.Collection;
12 import java.util.List;
13 import jp.sfjp.mikutoga.corelib.I18nText;
14 import jp.sfjp.mikutoga.math.MkPos3D;
15 import jp.sfjp.mikutoga.pmd.Deg3d;
16 import jp.sfjp.mikutoga.pmd.Rad3d;
17 import jp.sfjp.mikutoga.pmd.RigidShapeType;
18 import jp.sfjp.mikutoga.pmd.TripletRange;
19 import jp.sfjp.mikutoga.pmd.model.BoneInfo;
20 import jp.sfjp.mikutoga.pmd.model.DynamicsInfo;
21 import jp.sfjp.mikutoga.pmd.model.JointInfo;
22 import jp.sfjp.mikutoga.pmd.model.PmdModel;
23 import jp.sfjp.mikutoga.pmd.model.RigidGroup;
24 import jp.sfjp.mikutoga.pmd.model.RigidInfo;
25 import jp.sfjp.mikutoga.pmd.model.RigidShape;
26 import jp.sfjp.mikutoga.xml.ProxyXmlExporter;
27
28 /**
29  * 剛体力学設定のXMLエクスポーター。
30  */
31 class ExporterDynamics extends ProxyXmlExporter {
32
33     private static final String LEAD_REF = "Ref:";
34     private static final String RIGIDBEHAVIOR_COMMENT =
35           "Rigid behavior types:\n"
36         + "[0 : FOLLOWBONE    : ボーン追従       ]\n"
37         + "[1 : ONLYDYNAMICS  : 物理演算         ]\n"
38         + "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
39
40
41     private final ExtraExporter exp;
42
43
44     /**
45      * コンストラクタ。
46      * @param delegate 委譲先
47      */
48     ExporterDynamics(PmdXmlExporter delegate) {
49         super(delegate);
50         this.exp = new ExtraExporter(delegate);
51         return;
52     }
53
54     /**
55      * 剛体リストを出力する。
56      * @param model モデルデータ
57      * @throws IOException 出力エラー
58      */
59     void putRigidList(PmdModel model)
60             throws IOException{
61         ind().putSimpleSTag(PmdTag.RIGID_LIST.tag()).ln();
62         pushNest();
63
64         boolean dumped = false;
65         for(RigidInfo rigid : model.getRigidList()){
66             if( ! dumped ){
67                 ln().putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
68             }
69             putRigid(rigid);
70             dumped = true;
71         }
72
73         popNest();
74         ind().putETag(PmdTag.RIGID_LIST.tag()).ln(2);
75
76         return;
77     }
78
79     /**
80      * 個別の剛体情報を出力する。
81      * @param rigid 剛体情報
82      * @throws IOException 出力エラー
83      */
84     private void putRigid(RigidInfo rigid) throws IOException{
85         I18nText i18nName = rigid.getRigidName();
86         String primary = i18nName.getPrimaryText();
87
88         this.exp.putLocalNameComment(i18nName);
89         ln();
90
91         ind().putOpenSTag(PmdTag.RIGID.tag()).sp();
92         putAttr(PmdAttr.NAME.attr(), primary).sp();
93         this.exp.putNumberedIdAttr(PmdAttr.RIGID_ID,
94                 ExtraExporter.PFX_RIGID, rigid);
95         sp();
96         putAttr(PmdAttr.BEHAVIOR.attr(),
97                 rigid.getBehaviorType().name());
98         sp().putCloseSTag().ln();
99         pushNest();
100
101         this.exp.putI18nName(i18nName);
102         putRigidBody(rigid);
103
104         popNest();
105         ind().putETag(PmdTag.RIGID.tag()).ln(2);
106
107         return;
108     }
109
110     /**
111      * 剛体の詳細を出力する。
112      * @param rigid 剛体情報
113      * @throws IOException 出力エラー
114      */
115     private void putRigidBody(RigidInfo rigid) throws IOException{
116         BoneInfo linkedBone = rigid.getLinkedBone();
117         putLinkedBone(linkedBone);
118
119         RigidShape shape = rigid.getRigidShape();
120         putRigidShape(shape);
121
122         MkPos3D position = rigid.getPosition();
123         ind();
124         this.exp.putPosition(position);
125         ln();
126
127         Rad3d rotation = rigid.getRotation();
128         ind();
129         this.exp.putRadRotation(rotation);
130         ln();
131
132         DynamicsInfo dynamics = rigid.getDynamicsInfo();
133         putDynamics(dynamics);
134         ln();
135
136         Collection<RigidGroup> throughGroup = rigid.getThroughGroupColl();
137         putThroughRigid(throughGroup);
138
139         return;
140     }
141
142     /**
143      * 剛体接続ボーンを出力する。
144      * @param linkedBone 接続ボーン
145      * @throws IOException 出力エラー
146      */
147     private void putLinkedBone(BoneInfo linkedBone) throws IOException{
148         if(linkedBone == null) return;
149
150         ind().putOpenSTag(PmdTag.LINKED_BONE.tag()).sp();
151         this.exp.putNumberedIdAttr(PmdAttr.BONE_IDREF,
152                 ExtraExporter.PFX_BONE,
153                 linkedBone);
154         sp();
155         putCloseEmpty();
156         sp().putLineComment(LEAD_REF + linkedBone.getBoneName().getText());
157         ln(2);
158
159         return;
160     }
161
162     /**
163      * 剛体形状を出力する。
164      * @param shape 剛体形状
165      * @throws IOException 出力エラー
166      */
167     private void putRigidShape(RigidShape shape) throws IOException{
168         RigidShapeType type = shape.getShapeType();
169
170         switch(type){
171         case BOX:
172             ind().putOpenSTag(PmdTag.RIGID_SHAPE_BOX.tag()).sp();
173             putFloatAttr(PmdAttr.WIDTH.attr(),
174                     shape.getWidth()).sp();
175             putFloatAttr(PmdAttr.HEIGHT.attr(),
176                     shape.getHeight()).sp();
177             putFloatAttr(PmdAttr.DEPTH.attr(),
178                     shape.getDepth()).sp();
179             break;
180         case SPHERE:
181             ind().putOpenSTag(PmdTag.RIGID_SHAPE_SPHERE.tag()).sp();
182             putFloatAttr(PmdAttr.RADIUS.attr(),
183                     shape.getRadius()).sp();
184             break;
185         case CAPSULE:
186             ind().putOpenSTag(PmdTag.RIGID_SHAPE_CAPSULE.tag()).sp();
187             putFloatAttr(PmdAttr.HEIGHT.attr(),
188                     shape.getHeight()).sp();
189             putFloatAttr(PmdAttr.RADIUS.attr(),
190                     shape.getRadius()).sp();
191             break;
192         default:
193             assert false;
194             throw new AssertionError();
195         }
196
197         putCloseEmpty().ln();
198
199         return;
200     }
201
202     /**
203      * 力学設定を出力する。
204      * @param dynamics 力学設定
205      * @throws IOException 出力エラー
206      */
207     private void putDynamics(DynamicsInfo dynamics)
208             throws IOException{
209         ind().putOpenSTag(PmdTag.DYNAMICS.tag()).ln();
210         pushNest();
211         ind().putFloatAttr(PmdAttr.MASS.attr(),
212                 dynamics.getMass()).ln();
213         ind().putFloatAttr(PmdAttr.DAMPING_POSITION.attr(),
214                 dynamics.getDampingPosition()).ln();
215         ind().putFloatAttr(PmdAttr.DAMPING_ROTATION.attr(),
216                 dynamics.getDampingRotation()).ln();
217         ind().putFloatAttr(PmdAttr.RESTITUTION.attr(),
218                 dynamics.getRestitution()).ln();
219         ind().putFloatAttr(PmdAttr.FRICTION.attr(),
220                 dynamics.getFriction()).ln();
221         popNest();
222         ind().putCloseEmpty().ln();
223
224         return;
225     }
226
227     /**
228      * 通過剛体グループを出力する。
229      * @param groupColl 通過剛体グループ群
230      * @throws IOException 出力エラー
231      */
232     private void putThroughRigid(Collection<RigidGroup> groupColl)
233             throws IOException{
234         for(RigidGroup group : groupColl){
235             ind().putOpenSTag(PmdTag.THROUGH_RIGID_GROUP.tag()).sp();
236             this.exp
237                     .putNumberedIdAttr(PmdAttr.RIGID_GROUP_IDREF,
238                               ExtraExporter.PFX_RIGIDGROUP,
239                               group.getSerialNumber() + 1);
240             sp();
241             putCloseEmpty().ln();
242         }
243
244         return;
245     }
246
247     /**
248      * 剛体グループリストを出力する。
249      * @param model モデルデータ
250      * @throws IOException 出力エラー
251      */
252     void putRigidGroupList(PmdModel model)
253             throws IOException{
254         ind().putSimpleSTag(PmdTag.RIGID_GROUP_LIST.tag()).ln(2);
255         pushNest();
256
257         boolean singleLast = false;
258         for(RigidGroup group : model.getRigidGroupList()){
259             List<RigidInfo> rigidList = group.getRigidList();
260             if(singleLast &&  ! rigidList.isEmpty()){
261                 ln();
262             }
263             ind().putOpenSTag(PmdTag.RIGID_GROUP.tag()).sp();
264             this.exp.putNumberedIdAttr(PmdAttr.RIGID_GROUP_ID,
265                               ExtraExporter.PFX_RIGIDGROUP,
266                               group.getSerialNumber() + 1);
267             sp();
268             if(rigidList.isEmpty()){
269                 putCloseEmpty().ln();
270                 singleLast = true;
271                 continue;
272             }
273             putCloseSTag().ln();
274             pushNest();
275
276             for(RigidInfo rigid : rigidList){
277                 ind().putOpenSTag(PmdTag.RIGID_GROUP_MEMBER.tag()).sp();
278                 this.exp.putNumberedIdAttr(PmdAttr.RIGID_IDREF,
279                         ExtraExporter.PFX_RIGID, rigid);
280                 sp();
281                 putCloseEmpty();
282                 sp();
283                 putLineComment(LEAD_REF + rigid.getRigidName().getText());
284                 ln();
285             }
286
287             popNest();
288             ind().putETag(PmdTag.RIGID_GROUP.tag()).ln(2);
289             singleLast = false;
290         }
291
292         if(singleLast){
293             ln();
294         }
295
296         popNest();
297         ind().putETag(PmdTag.RIGID_GROUP_LIST.tag()).ln(2);
298
299         return;
300     }
301
302     /**
303      * ジョイントリストを出力する。
304      * @param model モデルデータ
305      * @throws IOException 出力エラー
306      */
307     void putJointList(PmdModel model)
308             throws IOException{
309         ind().putSimpleSTag(PmdTag.JOINT_LIST.tag()).ln();
310
311         pushNest();
312         boolean dumped = false;
313         List<JointInfo> jointList = model.getJointList();
314         for(JointInfo joint : jointList){
315             if( ! dumped ) ln();
316             putJoint(joint);
317             dumped = true;
318         }
319         popNest();
320
321         ind().putETag(PmdTag.JOINT_LIST.tag()).ln(2);
322
323         return;
324     }
325
326     /**
327      * 個別のジョイント情報を出力する。
328      * @param joint ジョイント情報
329      * @throws IOException 出力エラー
330      */
331     private void putJoint(JointInfo joint)
332             throws IOException{
333         I18nText i18nName = joint.getJointName();
334
335         this.exp.putLocalNameComment(i18nName);
336         ln();
337         ind().putOpenSTag(PmdTag.JOINT.tag()).sp();
338         this.exp.putPrimaryNameAttr(PmdAttr.NAME, i18nName);
339         sp().putCloseSTag().ln();
340         pushNest();
341
342         this.exp.putI18nName(i18nName);
343
344         RigidInfo rigidA = joint.getRigidA();
345         RigidInfo rigidB = joint.getRigidB();
346
347         ind();
348         putLineComment(
349                 "["
350                         + rigidA.getRigidName().getText()
351                 + "]\u0020<=>\u0020["
352                         + rigidB.getRigidName().getText()
353                 + "]");
354         ln();
355
356         ind().putOpenSTag(PmdTag.JOINTED_RIGID_PAIR.tag()).sp();
357         this.exp.putNumberedIdAttr(PmdAttr.RIGID_IDREF_1,
358                 ExtraExporter.PFX_RIGID, rigidA);
359         sp();
360         this.exp.putNumberedIdAttr(PmdAttr.RIGID_IDREF_2,
361                 ExtraExporter.PFX_RIGID, rigidB);
362         sp();
363         putCloseEmpty().ln(2);
364
365         putJointLimit(joint);
366         putJointElastic(joint);
367
368         popNest();
369         ind().putETag(PmdTag.JOINT.tag()).ln(2);
370
371         return;
372     }
373
374     /**
375      * ジョイント制限情報を出力する。
376      * @param joint ジョイント情報
377      * @throws IOException 出力エラー
378      */
379     private void putJointLimit(JointInfo joint)
380             throws IOException{
381         MkPos3D position = joint.getPosition();
382         ind();
383         this.exp.putPosition(position);
384         ln();
385
386         ind().putOpenSTag(PmdTag.LIMIT_POSITION.tag()).ln();
387         pushNest();
388         TripletRange posRange = joint.getPositionRange();
389         putTripletRangeAttr(posRange);
390         popNest();
391         ind().putCloseEmpty().ln(2);
392
393         Rad3d rotation = joint.getRotation();
394         ind();
395         this.exp.putRadRotation(rotation);
396         ln();
397
398         ind().putOpenSTag(PmdTag.LIMIT_ROTATION.tag()).ln();
399         pushNest();
400         TripletRange rotRange = joint.getRotationRange();
401         putTripletRangeAttr(rotRange);
402         popNest();
403         ind().putCloseEmpty().ln(2);
404
405         return;
406     }
407
408     /**
409      * XYZ範囲属性を出力する。
410      * @param range XYZ範囲
411      * @throws IOException 出力エラー
412      */
413     private void putTripletRangeAttr(TripletRange range)
414             throws IOException{
415         ind();
416         putFloatAttr(PmdAttr.X_FROM.attr(), range.getXFrom()).sp();
417         putFloatAttr(PmdAttr.X_TO.attr(),   range.getXTo()  ).ln();
418
419         ind();
420         putFloatAttr(PmdAttr.Y_FROM.attr(), range.getYFrom()).sp();
421         putFloatAttr(PmdAttr.Y_TO.attr(),   range.getYTo()  ).ln();
422
423         ind();
424         putFloatAttr(PmdAttr.Z_FROM.attr(), range.getZFrom()).sp();
425         putFloatAttr(PmdAttr.Z_TO.attr(),   range.getZTo()  ).ln();
426
427         return;
428     }
429
430     /**
431      * ジョイント弾性情報を出力する。
432      * @param joint ジョイント情報
433      * @throws IOException 出力エラー
434      */
435     private void putJointElastic(JointInfo joint)
436             throws IOException{
437         ind().putOpenSTag(PmdTag.ELASTIC_POSITION.tag()).sp();
438         MkPos3D elaPosition = joint.getElasticPosition();
439         putFloatAttr(PmdAttr.X.attr(),
440                 (float) elaPosition.getXpos()).sp();
441         putFloatAttr(PmdAttr.Y.attr(),
442                 (float) elaPosition.getYpos()).sp();
443         putFloatAttr(PmdAttr.Z.attr(),
444                 (float) elaPosition.getZpos()).sp();
445         putCloseEmpty().ln();
446
447         ind().putOpenSTag(PmdTag.ELASTIC_ROTATION.tag()).sp();
448         Deg3d elaRotation = joint.getElasticRotation();
449         putFloatAttr(PmdAttr.X_DEG.attr(),
450                 elaRotation.getXDeg()).sp();
451         putFloatAttr(PmdAttr.Y_DEG.attr(),
452                 elaRotation.getYDeg()).sp();
453         putFloatAttr(PmdAttr.Z_DEG.attr(),
454                 elaRotation.getZDeg()).sp();
455         putCloseEmpty().ln(2);
456
457         return;
458     }
459
460 }