OSDN Git Service

86d7e46aba59db1bb019bda664e5427c61c92752
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd / model / xml / RefHelper.java
1 /*
2  * SAX ID-reference helper
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.util.Collection;
11 import java.util.HashMap;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.Map;
15 import jp.sfjp.mikutoga.pmd.model.BoneInfo;
16 import jp.sfjp.mikutoga.pmd.model.Material;
17 import jp.sfjp.mikutoga.pmd.model.MorphVertex;
18 import jp.sfjp.mikutoga.pmd.model.RigidGroup;
19 import jp.sfjp.mikutoga.pmd.model.RigidInfo;
20 import jp.sfjp.mikutoga.pmd.model.ShadeInfo;
21 import jp.sfjp.mikutoga.pmd.model.Surface;
22 import jp.sfjp.mikutoga.pmd.model.Vertex;
23
24 /**
25  * 各種ID参照解決用の一時的なヘルパ。
26  */
27 class RefHelper {
28
29     // マテリアル関連
30     private final List<IdRefHolder<Material>> materialSfcGroupIdRefList =
31             new LinkedList<IdRefHolder<Material>>();
32     private final List<IdRefHolder<Material>> materialToonIdRefList =
33             new LinkedList<IdRefHolder<Material>>();
34     private final Map<String, Integer> toonIdxMap =
35             new HashMap<String, Integer>();
36
37     // ボーン関連
38     private final Map<String, BoneInfo> boneIdMap =
39             new HashMap<String, BoneInfo>();
40     private final List<IdRefHolder<BoneInfo>> boneChainIdRefList =
41             new LinkedList<IdRefHolder<BoneInfo>>();
42     private final List<IdRefHolder<BoneInfo>> boneSourceIdRefList =
43             new LinkedList<IdRefHolder<BoneInfo>>();
44
45     // モーフ関連
46     private final List<IdRefHolder<MorphVertex>> morphVertexIdRefList =
47             new LinkedList<IdRefHolder<MorphVertex>>();
48
49     // 剛体関連
50     private final Map<String, RigidInfo> rigidIdMap =
51             new HashMap<String, RigidInfo>();
52     private final Map<String, RigidGroup> rigidGroupIdMap =
53             new HashMap<String, RigidGroup>();
54     private final List<IdRefHolder<RigidInfo>> thghRigidGroupIdRefList =
55             new LinkedList<IdRefHolder<RigidInfo>>();
56
57     // 面関連
58     private final Map<String, List<Surface>> surfaceGroupIdMap =
59             new HashMap<String, List<Surface>>();
60     private final List<IdRefHolder<Surface>> surfaceVertexIdRef =
61             new LinkedList<IdRefHolder<Surface>>();
62
63     // 頂点関連
64     private final Map<String, Vertex> vertexIdMap =
65             new HashMap<String, Vertex>();
66
67
68     /**
69      * コンストラクタ。
70      */
71     RefHelper(){
72         super();
73         return;
74     }
75
76
77     /**
78      * マテリアルからのサーフェイスグループID参照を登録する。
79      * @param material マテリアル
80      * @param idRef サーフェイスグループID参照
81      */
82     void addSurfaceGroupIdRef(Material material, String idRef){
83         IdRefHolder<Material> holder =
84                 new IdRefHolder<Material>(material, idRef);
85         this.materialSfcGroupIdRefList.add(holder);
86
87         return;
88     }
89
90     /**
91      * サーフェイスグループの構成サーフェイスを登録する。
92      * @param surfaceGroupId サーフェイスグループID
93      * @param surface サーフェイス
94      */
95     void addSurfaceGroup(String surfaceGroupId, Surface surface){
96         List<Surface> surfaceGroup =
97                 this.surfaceGroupIdMap.get(surfaceGroupId);
98         if(surfaceGroup == null){
99             surfaceGroup = new LinkedList<Surface>();
100             this.surfaceGroupIdMap.put(surfaceGroupId, surfaceGroup);
101         }
102
103         surfaceGroup.add(surface);
104
105         return;
106     }
107
108     /**
109      * マテリアルからのサーフェイスグループID参照を解決する。
110      */
111     void resolveMaterialSurfaceGroupId(){
112         for(IdRefHolder<Material> holder : this.materialSfcGroupIdRefList){
113             Material material = holder.getBody();
114             String surfaceGroupIdRef = holder.getIdRef();
115
116             List<Surface> surfaceGroup =
117                     this.surfaceGroupIdMap.get(surfaceGroupIdRef);
118
119             List<Surface> surfaceList = material.getSurfaceList();
120             surfaceList.addAll(surfaceGroup);
121         }
122
123         return;
124     }
125
126     /**
127      * マテリアルからの共有トゥーンファイルID参照を追加登録する。
128      * @param material マテリアル
129      * @param idRef トゥーンファイルID参照
130      */
131     void addToonFileIdRef(Material material, String idRef){
132         IdRefHolder<Material> holder =
133                 new IdRefHolder<Material>(material, idRef);
134         this.materialToonIdRefList.add(holder);
135         return;
136     }
137
138     /**
139      * 共有トゥーンファイルのインデックスを登録する。
140      * @param toonFileId ToonファイルID
141      * @param idx 共有Toonインデックス
142      */
143     void addToonIdx(String toonFileId, int idx){
144         this.toonIdxMap.put(toonFileId, idx);
145         return;
146     }
147
148     /**
149      * マテリアルからの共有トゥーンインデックスの参照問題を解決する。
150      */
151     void resolveToonIdx(){
152         for(IdRefHolder<Material> holder : this.materialToonIdRefList){
153             Material material = holder.getBody();
154             String toonFileIdRef = holder.getIdRef();
155             int toonIdx = this.toonIdxMap.get(toonFileIdRef);
156
157             ShadeInfo shadeInfo = material.getShadeInfo();
158             shadeInfo.setToonIndex(toonIdx);
159         }
160
161         return;
162     }
163
164     /**
165      * ボーンIDを登録する。
166      * @param boneId ボーンID
167      * @param boneInfo ボーン情報
168      */
169     void addBoneId(String boneId, BoneInfo boneInfo){
170         this.boneIdMap.put(boneId, boneInfo);
171         return;
172     }
173
174     /**
175      * ボーンIDを問い合わせる。
176      * @param boneId ボーンID
177      * @return ボーン情報
178      */
179     BoneInfo findBoneId(String boneId){
180         BoneInfo result = this.boneIdMap.get(boneId);
181         return result;
182     }
183
184     /**
185      * ボーン間チェーン参照情報を登録する。
186      * @param bone ボーン情報
187      * @param prevBoneIdRef 前ボーンID参照
188      * @param nextBoneIdRef 次ボーンID参照
189      */
190     void addBoneChain(BoneInfo bone,
191                         String prevBoneIdRef, String nextBoneIdRef ){
192         IdRefHolder<BoneInfo> holder =
193                 new IdRefHolder<BoneInfo>(bone, prevBoneIdRef, nextBoneIdRef);
194         this.boneChainIdRefList.add(holder);
195         return;
196     }
197
198     /**
199      * ボーン間チェーン参照情報を解決する。
200      */
201     void resolveBoneChainIdRef(){
202         for(IdRefHolder<BoneInfo> holder : this.boneChainIdRefList){
203             BoneInfo bone = holder.getBody();
204             String prevBoneIdRef = holder.getIdRef();
205             String nextBoneIdRef = holder.getIdRef2();
206
207             if(prevBoneIdRef != null){
208                 BoneInfo prevBone = this.boneIdMap.get(prevBoneIdRef);
209                 bone.setPrevBone(prevBone);
210             }
211
212             if(nextBoneIdRef != null){
213                 BoneInfo nextBone = this.boneIdMap.get(nextBoneIdRef);
214                 bone.setNextBone(nextBone);
215             }
216         }
217
218         return;
219     }
220
221     /**
222      * ボーン情報からのソースボーンID参照を登録する。
223      * @param bone ボーン情報
224      * @param srcBoneIdRef ソースボーンID参照
225      */
226     void addSrcBoneIdRef(BoneInfo bone, String srcBoneIdRef){
227         IdRefHolder<BoneInfo> holder =
228                 new IdRefHolder<BoneInfo>(bone, srcBoneIdRef);
229         this.boneSourceIdRefList.add(holder);
230         return;
231     }
232
233     /**
234      * ボーン情報からのソースボーンID参照を解決する。
235      */
236     void resolveSrcBoneIdRef(){
237         for(IdRefHolder<BoneInfo> holder : this.boneSourceIdRefList){
238             BoneInfo bone = holder.getBody();
239             String srcBoneIdRef = holder.getIdRef();
240             if(srcBoneIdRef == null) continue;
241
242             BoneInfo srcBone = this.boneIdMap.get(srcBoneIdRef);
243             bone.setSrcBone(srcBone);
244         }
245
246         return;
247     }
248
249     /**
250      * モーフ頂点からの頂点ID参照を登録する。
251      * @param morphVertex モーフ頂点
252      * @param vertexIdRef 頂点ID参照
253      */
254     void addMorphVertexIdRef(MorphVertex morphVertex, String vertexIdRef){
255         IdRefHolder<MorphVertex> holder =
256                 new IdRefHolder<MorphVertex>(morphVertex, vertexIdRef);
257         this.morphVertexIdRefList.add(holder);
258         return;
259     }
260
261     /**
262      * 剛体IDを登録する。
263      * @param rigidId 剛体ID
264      * @param rigid 剛体情報
265      */
266     void addRigidId(String rigidId, RigidInfo rigid){
267         this.rigidIdMap.put(rigidId, rigid);
268         return;
269     }
270
271     /**
272      * 剛体IDを問い合わせる。
273      * @param rigidId 剛体ID
274      * @return 剛体情報
275      */
276     RigidInfo findRigidId(String rigidId){
277         RigidInfo result = this.rigidIdMap.get(rigidId);
278         return result;
279     }
280
281     /**
282      * 剛体からの通過剛体グループID参照を登録する。
283      * @param rigid 剛体情報
284      * @param rigidGroupIdRef 剛体グループID参照
285      */
286     void addThroughRigidGroupIdRef(RigidInfo rigid, String rigidGroupIdRef){
287         IdRefHolder<RigidInfo> holder =
288                 new IdRefHolder<RigidInfo>(rigid, rigidGroupIdRef);
289         this.thghRigidGroupIdRefList.add(holder);
290         return;
291     }
292
293     /**
294      * 剛体グループIDを登録する。
295      * @param rigidGroupId 剛体グループID
296      * @param rigidGroup 剛体グループ
297      */
298     void addRigidGroupId(String rigidGroupId, RigidGroup rigidGroup){
299         this.rigidGroupIdMap.put(rigidGroupId, rigidGroup);
300         return;
301     }
302
303     /**
304      * 剛体グループID参照を解決する。
305      */
306     void resolveThroughRigidGroupIdRef(){
307         for(IdRefHolder<RigidInfo> holder : this.thghRigidGroupIdRefList){
308             RigidInfo rigid = holder.getBody();
309             String rigidGroupIdRef = holder.getIdRef();
310             RigidGroup group = this.rigidGroupIdMap.get(rigidGroupIdRef);
311
312             Collection<RigidGroup> throughGroups =
313                     rigid.getThroughGroupColl();
314             throughGroups.add(group);
315         }
316
317         return;
318     }
319
320     /**
321      * 三角ポリゴンサーフェイス面からの頂点ID参照を登録する。
322      * @param surface surface面
323      * @param vtxIdRef1 頂点ID参照その1
324      * @param vtxIdRef2 頂点ID参照その2
325      * @param vtxIdRef3 頂点ID参照その3
326      */
327     void addSurfaceVertex(Surface surface,
328                             String vtxIdRef1,
329                             String vtxIdRef2,
330                             String vtxIdRef3 ){
331         IdRefHolder<Surface> holder =
332                 new IdRefHolder<Surface>(surface,
333                                          vtxIdRef1,
334                                          vtxIdRef2,
335                                          vtxIdRef3 );
336
337         this.surfaceVertexIdRef.add(holder);
338
339         return;
340     }
341
342     /**
343      * 頂点IDを登録する。
344      * @param vertexId 頂点ID
345      * @param vertex 頂点
346      */
347     void addVertexId(String vertexId, Vertex vertex){
348         this.vertexIdMap.put(vertexId, vertex);
349         return;
350     }
351
352     /**
353      * モーフ頂点からの頂点ID参照を解決する。
354      */
355     void resolveMorphVertexIdRef(){
356         for(IdRefHolder<MorphVertex> holder : this.morphVertexIdRefList){
357             MorphVertex morphVertex = holder.getBody();
358             String vertexIdRef = holder.getIdRef();
359             Vertex vertex = this.vertexIdMap.get(vertexIdRef);
360
361             morphVertex.setBaseVertex(vertex);
362         }
363
364         return;
365     }
366
367     /**
368      * サーフェイスからの頂点ID参照を解決する。
369      */
370     void resolveSurfaceVertexIdRef(){
371         for(IdRefHolder<Surface> holder : this.surfaceVertexIdRef){
372             Surface surface = holder.getBody();
373             String vertexIdRef1 = holder.getIdRef();
374             String vertexIdRef2 = holder.getIdRef2();
375             String vertexIdRef3 = holder.getIdRef3();
376
377             Vertex vtx1 = this.vertexIdMap.get(vertexIdRef1);
378             Vertex vtx2 = this.vertexIdMap.get(vertexIdRef2);
379             Vertex vtx3 = this.vertexIdMap.get(vertexIdRef3);
380
381             surface.setTriangle(vtx1, vtx2, vtx3);
382         }
383
384         return;
385     }
386
387     /**
388      * ID参照解決用一時ホルダ。
389      * 必要に応じて参照IDを3つまで持てる。
390      * @param <E> ID参照元インスタンス型
391      */
392     private static final class IdRefHolder<E> {
393
394         private final E body;
395
396         private final String idRef;
397         private final String idRef2;
398         private final String idRef3;
399
400         /**
401          * コンストラクタ。
402          * @param body ID参照元インスタンス
403          * @param idRef 参照ID
404          */
405         IdRefHolder(E body, String idRef){
406             this(body, idRef, null, null);
407             return;
408         }
409
410         /**
411          * コンストラクタ。
412          * @param body ID参照元インスタンス
413          * @param idRef 参照ID
414          * @param idRef2 参照IDその2
415          */
416         IdRefHolder(E body, String idRef, String idRef2){
417             this(body, idRef, idRef2, null);
418             return;
419         }
420
421         /**
422          * コンストラクタ。
423          * @param body ID参照元インスタンス
424          * @param idRef  参照ID
425          * @param idRef2 参照IDその2
426          * @param idRef3 参照IDその3
427          */
428         IdRefHolder(E body,
429                       String idRef,
430                       String idRef2,
431                       String idRef3 ){
432             super();
433
434             this.body = body;
435
436             this.idRef  = idRef;
437             this.idRef2 = idRef2;
438             this.idRef3 = idRef3;
439
440             return;
441         }
442
443
444         /**
445          * ID参照元インスタンスを返す。
446          * @return ID参照元インスタンス
447          */
448         private E getBody(){
449             return this.body;
450         }
451
452         /**
453          * 参照IDを返す。
454          * @return 参照ID
455          */
456         private String getIdRef(){
457             return this.idRef;
458         }
459
460         /**
461          * 参照IDその2を返す。
462          * @return 参照ID
463          */
464         private String getIdRef2(){
465             return this.idRef2;
466         }
467
468         /**
469          * 参照IDその3を返す。
470          * @return 参照ID
471          */
472         private String getIdRef3(){
473             return this.idRef3;
474         }
475
476     }
477
478 }