OSDN Git Service

checkstyle対応
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd / model / PmdModel.java
1 /*
2  * PMD model
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.pmd.model;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.EnumMap;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.LinkedList;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.RandomAccess;
19 import java.util.Set;
20 import jp.sfjp.mikutoga.corelib.I18nText;
21 import jp.sfjp.mikutoga.pmd.MorphType;
22
23 /**
24  * PMDモデルファイル一式に相当するもの。
25  * 様々な基本構造のリストの集合から構成される。
26  */
27 public class PmdModel {
28
29     private final I18nText modelName = new I18nText();
30     private final I18nText description = new I18nText();
31
32     private final List<Vertex> vertexList = new ArrayList<Vertex>();
33     private final List<Surface> surfaceList = new ArrayList<Surface>();
34     private final List<Material> materialList = new LinkedList<Material>();
35
36     private final List<BoneInfo> boneList = new ArrayList<BoneInfo>();
37     private final List<BoneGroup> boneGroupList = new ArrayList<BoneGroup>();
38
39     private final List<IKChain> ikChainList = new ArrayList<IKChain>();
40
41     private final Map<MorphType, List<MorphPart>> morphMap =
42             new EnumMap<MorphType, List<MorphPart>>(MorphType.class);
43
44     private final List<RigidInfo> rigidList = new ArrayList<RigidInfo>();
45     private final List<RigidGroup> rigidGroupList =
46             new ArrayList<RigidGroup>();
47
48     private final List<JointInfo> jointList = new ArrayList<JointInfo>();
49
50     private ToonMap toonMap = new ToonMap();
51
52
53     /**
54      * コンストラクタ。
55      */
56     public PmdModel(){
57         super();
58
59         assert this.vertexList instanceof RandomAccess;
60         assert this.surfaceList instanceof RandomAccess;
61
62         this.morphMap.put(MorphType.EYEBROW, new ArrayList<MorphPart>());
63         this.morphMap.put(MorphType.EYE,     new ArrayList<MorphPart>());
64         this.morphMap.put(MorphType.LIP,     new ArrayList<MorphPart>());
65         this.morphMap.put(MorphType.EXTRA,   new ArrayList<MorphPart>());
66
67         return;
68     }
69
70
71     /**
72      * モデル名を返す。
73      * @return モデル名
74      */
75     public I18nText getModelName(){
76         return this.modelName;
77     }
78
79     /**
80      * モデル説明文を返す。
81      * 改行表現には{@literal \n}が用いられる
82      * @return モデル説明文
83      */
84     public I18nText getDescription(){
85         return this.description;
86     }
87
88     /**
89      * 頂点リストを返す。
90      * @return 頂点リスト。
91      */
92     public List<Vertex> getVertexList(){
93         return this.vertexList;
94     }
95
96     /**
97      * 面リストを返す。
98      * @return 面リスト
99      */
100     public List<Surface> getSurfaceList(){
101         return this.surfaceList;
102     }
103
104     /**
105      * 素材リストを返す。
106      * @return 素材リスト
107      */
108     public List<Material> getMaterialList(){
109         return this.materialList;
110     }
111
112     /**
113      * ボーンリストを返す。
114      * @return ボーンリスト
115      */
116     public List<BoneInfo> getBoneList(){
117         return this.boneList;
118     }
119
120     /**
121      * ボーングループリストを返す。
122      * @return ボーングループリスト
123      */
124     public List<BoneGroup> getBoneGroupList(){
125         return this.boneGroupList;
126     }
127
128     /**
129      * IKチェーンリストを返す。
130      * @return IKチェーンリスト
131      */
132     public List<IKChain> getIKChainList(){
133         return this.ikChainList;
134     }
135
136     /**
137      * 種類別モーフリストのマップを返す。
138      * @return 種類別モーフリストのマップ
139      */
140     public Map<MorphType, List<MorphPart>> getMorphMap(){
141         return this.morphMap;
142     }
143
144     /**
145      * 剛体リストを返す。
146      * @return 剛体リスト
147      */
148     public List<RigidInfo> getRigidList(){
149         return this.rigidList;
150     }
151
152     /**
153      * 剛体グループリストを返す。
154      * @return 剛体グループリスト。
155      */
156     public List<RigidGroup> getRigidGroupList(){
157         return this.rigidGroupList;
158     }
159
160     /**
161      * 剛体間ジョイントリストを返す。
162      * @return 剛体間ジョイントリスト
163      */
164     public List<JointInfo> getJointList(){
165         return this.jointList;
166     }
167
168     /**
169      * トゥーンファイルマップを返す。
170      * @return トゥーンファイルマップ
171      */
172     public ToonMap getToonMap(){
173         return this.toonMap;
174     }
175
176     /**
177      * トゥーンファイルマップを設定する。
178      * 各素材のシェーディングで参照するトゥーンファイルマップも更新される。
179      * @param map トゥーンファイルマップ
180      */
181     public void setToonMap(ToonMap map){
182         this.toonMap = map;
183         for(Material material : this.materialList){
184             ShadeInfo info = material.getShadeInfo();
185             info.setToonMap(this.toonMap);
186         }
187         return;
188     }
189
190     /**
191      * このモデルがグローバル名を含むか判定する。
192      * ボーン名、ボーングループ名、モーフ名、モデル説明文が判定対象。
193      * @return グローバル名を持つならtrue
194      */
195     public boolean hasGlobalText(){
196         if(this.modelName.hasGlobalText()) return true;
197         if(this.description.hasGlobalText()) return true;
198
199         for(BoneInfo bone : this.boneList){
200             if(bone.getBoneName().hasGlobalText()) return true;
201         }
202
203         for(List<MorphPart> partList : this.morphMap.values()){
204             for(MorphPart part : partList){
205                 if(part.getMorphName().hasGlobalText()) return true;
206             }
207         }
208
209         for(BoneGroup group : this.boneGroupList){
210             if(group.getGroupName().hasGlobalText()) return true;
211         }
212
213         return false;
214     }
215
216     /**
217      * 全モーフが使う全モーフ頂点の出現順リストを返す。
218      * モーフ種別毎に固まっている事が保証される。
219      * @return モーフ頂点リスト
220      */
221     private List<MorphVertex> getAllMorphVertexList(){
222         List<MorphVertex> allList = new ArrayList<MorphVertex>();
223
224         for(MorphType type : this.morphMap.keySet()){
225             if(type.isBase()) continue;
226
227             List<MorphPart> partList = this.morphMap.get(type);
228             if(partList == null) continue;
229
230             for(MorphPart part : partList){
231                 List<MorphVertex> morphVertexList =
232                         part.getMorphVertexList();
233                 allList.addAll(morphVertexList);
234             }
235         }
236
237         return allList;
238     }
239
240     /**
241      * 重複する頂点参照を除いたモーフ頂点リストを返す。
242      * @param allList モーフ頂点リスト
243      * @return 重複が除かれたモーフ頂点リスト
244      */
245     private List<MorphVertex> getUniqueMorphVertexList(
246             List<MorphVertex> allList ){
247         List<MorphVertex> result = new ArrayList<MorphVertex>();
248
249         Set<Vertex> mergedVertexSet = new HashSet<Vertex>();
250
251         for(MorphVertex morphVertex : allList){
252             Vertex vertex = morphVertex.getBaseVertex();
253
254             if(mergedVertexSet.contains(vertex)) continue;
255
256             mergedVertexSet.add(vertex);
257             result.add(morphVertex);
258         }
259
260         return result;
261     }
262
263     /**
264      * モーフで使われる全てのモーフ頂点のリストを返す。
265      * モーフ間で重複する頂点はマージされる。
266      * 頂点IDでソートされる。
267      * <p>
268      * 0から始まる通し番号がリナンバリングされる。
269      * 通し番号は返されるモーフ頂点リストの添え字番号と一致する。
270      * @return モーフに使われるモーフ頂点のリスト
271      */
272     public List<MorphVertex> mergeMorphVertex(){
273         List<MorphVertex> result;
274
275         List<MorphVertex> allList = getAllMorphVertexList();
276         result = getUniqueMorphVertexList(allList);
277
278         Collections.sort(result, MorphVertex.VIDCOMPARATOR);
279         ListUtil.assignIndexedSerial(result);
280
281         Map<Vertex, MorphVertex> numberedMap =
282                 new HashMap<Vertex, MorphVertex>();
283         for(MorphVertex morphVertex : result){
284             Vertex vertex = morphVertex.getBaseVertex();
285             numberedMap.put(vertex, morphVertex);
286         }
287
288         for(MorphVertex morphVertex : allList){
289             Vertex vertex = morphVertex.getBaseVertex();
290
291             MorphVertex numbered = numberedMap.get(vertex);
292             assert numbered != null;
293
294             int serialNo = numbered.getSerialNumber();
295             morphVertex.setSerialNumber(serialNo);
296         }
297
298         return result;
299     }
300
301     /**
302      * 永続化可能な状態へトリミングする。
303      * 各種オブジェクトの通し番号が変化する可能性がある。
304      */
305     public void trimming(){
306         List<Surface> trimmedSurfaceList = trimmingSurfaceList();
307         this.surfaceList.clear();
308         this.surfaceList.addAll(trimmedSurfaceList);
309
310         List<Vertex> trimmedVertexList = trimmingVertexList();
311         this.vertexList.clear();
312         this.vertexList.addAll(trimmedVertexList);
313
314         return;
315     }
316
317     /**
318      * 面リストをトリミングする。
319      * 所属マテリアル順に再配置し、通し番号を割り振り直す。
320      * 所属マテリアルの無い面はリストの末端に配置される。
321      * 面リスト中のnullは削除され詰められる。
322      * @return トリミングされた面リスト
323      */
324     private List<Surface> trimmingSurfaceList(){
325         Set<Surface> materialedSurfaceSet = new HashSet<Surface>();
326         for(Material material : this.materialList){
327             if(material == null) continue;
328             for(Surface surface : material){
329                 if(surface == null) continue;
330                 materialedSurfaceSet.add(surface);
331             }
332         }
333
334         materialedSurfaceSet.removeAll(this.surfaceList);
335
336         List<Surface> result = new ArrayList<Surface>();
337         for(Surface surface : this.surfaceList){
338             if(surface == null) continue;
339             result.add(surface);
340         }
341
342         result.addAll(materialedSurfaceSet);
343
344         int serialNum = 0;
345         for(Surface surface : result){
346             surface.setSerialNumber(serialNum);
347             serialNum++;
348         }
349
350         return result;
351     }
352
353     /**
354      * 頂点リストをトリミングする。
355      * 通し番号を振り直す。
356      * 所属面の無い頂点はリストの末端に配置される。
357      * 頂点リスト中のnullは削除され詰められる。
358      * @return トリミングされた頂点リスト
359      */
360     private List<Vertex> trimmingVertexList(){
361         Set<Vertex> surfacedVertexSet = new HashSet<Vertex>();
362         for(Surface surface : this.surfaceList){
363             if(surface == null) continue;
364             for(Vertex vertex : surface){
365                 surfacedVertexSet.add(vertex);
366             }
367         }
368
369         surfacedVertexSet.removeAll(this.vertexList);
370
371         List<Vertex> result = new ArrayList<Vertex>();
372         for(Vertex vertex : this.vertexList){
373             if(vertex == null) continue;
374             result.add(vertex);
375         }
376
377         result.addAll(surfacedVertexSet);
378
379         int serialNum = 0;
380         for(Vertex vertex : result){
381             vertex.setSerialNumber(serialNum);
382             serialNum++;
383         }
384
385         return result;
386     }
387
388 }