OSDN Git Service

343d4c3f390f54fa261c658cfbde5f0feec01aef
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd / binio / BoneBuilder.java
1 /*
2  * building bone information
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.pmd.binio;
9
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import jp.sfjp.mikutoga.bin.parser.ParseStage;
14 import jp.sfjp.mikutoga.math.MkPos3D;
15 import jp.sfjp.mikutoga.pmd.BoneType;
16 import jp.sfjp.mikutoga.pmd.PmdLimits;
17 import jp.sfjp.mikutoga.pmd.model.BoneGroup;
18 import jp.sfjp.mikutoga.pmd.model.BoneInfo;
19 import jp.sfjp.mikutoga.pmd.model.IKChain;
20 import jp.sfjp.mikutoga.pmd.model.ListUtil;
21 import jp.sfjp.mikutoga.pmd.model.PmdModel;
22 import jp.sfjp.mikutoga.pmd.parser.PmdBoneHandler;
23
24 /**
25  * ボーン関係の通知をパーサから受け取る。
26  */
27 class BoneBuilder implements PmdBoneHandler {
28
29     private final List<BoneInfo> boneList;
30     private Iterator<BoneInfo> boneIt;
31     private BoneInfo currentBone = null;
32
33     private final List<IKChain> ikChainList;
34     private Iterator<IKChain> ikChainIt;
35     private IKChain currentIkChain = null;
36
37     private final List<BoneGroup> boneGroupList;
38     private Iterator<BoneGroup> boneGroupIt;
39     private BoneGroup currentBoneGroup = null;
40
41     /**
42      * コンストラクタ。
43      * @param model モデル
44      */
45     BoneBuilder(PmdModel model){
46         super();
47
48         this.boneList      = model.getBoneList();
49         this.ikChainList   = model.getIKChainList();
50         this.boneGroupList = model.getBoneGroupList();
51
52         return;
53     }
54
55     /**
56      * {@inheritDoc}
57      * @param stage {@inheritDoc}
58      * @param loops {@inheritDoc}
59      */
60     @Override
61     public void loopStart(ParseStage stage, int loops){
62         if(stage == PmdBoneHandler.BONE_LIST){
63             ListUtil.prepareDefConsList(this.boneList, BoneInfo.class, loops);
64             ListUtil.assignIndexedSerial(this.boneList);
65
66             this.boneIt = this.boneList.iterator();
67             if(this.boneIt.hasNext()){
68                 this.currentBone = this.boneIt.next();
69             }
70         }else if(stage == PmdBoneHandler.IK_LIST){
71             ListUtil.prepareDefConsList(this.ikChainList,
72                                         IKChain.class,
73                                         loops );
74
75             this.ikChainIt = this.ikChainList.iterator();
76             if(this.ikChainIt.hasNext()){
77                 this.currentIkChain = this.ikChainIt.next();
78             }
79         }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
80             //NOTHING
81         }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
82             ListUtil.prepareDefConsList(this.boneGroupList,
83                                         BoneGroup.class,
84                                         loops + 1 );
85             ListUtil.assignIndexedSerial(this.boneGroupList);
86
87             this.boneGroupIt = this.boneGroupList.iterator();
88
89             assert this.boneGroupIt.hasNext();
90             this.boneGroupIt.next();     // デフォルトボーングループを読み飛ばす
91
92             if(this.boneGroupIt.hasNext()){
93                 this.currentBoneGroup = this.boneGroupIt.next();
94             }
95         }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
96             //NOTHING
97         }else{
98             assert false;
99             throw new AssertionError();
100         }
101
102         return;
103     }
104
105     /**
106      * {@inheritDoc}
107      * @param stage {@inheritDoc}
108      */
109     @Override
110     public void loopNext(ParseStage stage){
111         if(stage == PmdBoneHandler.BONE_LIST){
112             if(this.boneIt.hasNext()){
113                 this.currentBone = this.boneIt.next();
114             }
115         }else if(stage == PmdBoneHandler.IK_LIST){
116             if(this.ikChainIt.hasNext()){
117                 this.currentIkChain = this.ikChainIt.next();
118             }
119         }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
120             //NOTHING
121         }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
122             if(this.boneGroupIt.hasNext()){
123                 this.currentBoneGroup = this.boneGroupIt.next();
124             }
125         }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
126             //NOTHING
127         }else{
128             assert false;
129             throw new AssertionError();
130         }
131         return;
132     }
133
134     /**
135      * {@inheritDoc}
136      * @param stage {@inheritDoc}
137      */
138     @Override
139     public void loopEnd(ParseStage stage){
140         if(stage == PmdBoneHandler.BONE_LIST){
141             //NOTHING
142         }else if(stage == PmdBoneHandler.IK_LIST){
143             //NOTHING
144         }else if(stage == PmdBoneHandler.IKCHAIN_LIST){
145             //NOTHING
146         }else if(stage == PmdBoneHandler.BONEGROUP_LIST){
147             //NOTHING
148         }else if(stage == PmdBoneHandler.GROUPEDBONE_LIST){
149             pickOrphanBone();
150         }else{
151             assert false;
152             throw new AssertionError();
153         }
154         return;
155     }
156
157     /**
158      * 所属グループの無いボーンをデフォルトボーングループへ登録する。
159      */
160     private void pickOrphanBone(){
161         List<BoneInfo> orpahnList = new LinkedList<BoneInfo>();
162         orpahnList.addAll(this.boneList);
163         for(BoneGroup group : this.boneGroupList){
164             orpahnList.removeAll(group.getBoneList());
165         }
166
167         BoneGroup defaultGroup = this.boneGroupList.get(0);
168         defaultGroup.getBoneList().addAll(orpahnList);
169
170         return;
171     }
172
173     /**
174      * {@inheritDoc}
175      * @param boneName {@inheritDoc}
176      * @param boneKind {@inheritDoc}
177      */
178     @Override
179     public void pmdBoneInfo(String boneName, byte boneKind){
180         this.currentBone.getBoneName().setPrimaryText(boneName);
181         BoneType type = BoneType.decode(boneKind);
182         this.currentBone.setBoneType(type);
183         return;
184     }
185
186     /**
187      * {@inheritDoc}
188      * @param parentId {@inheritDoc}
189      * @param tailId {@inheritDoc}
190      * @param srcId {@inheritDoc}
191      */
192     @Override
193     public void pmdBoneLink(int parentId, int tailId, int srcId){
194         BoneInfo prevBone = null;
195         if(0 <= parentId && parentId < PmdLimits.MAX_BONE){
196             prevBone = this.boneList.get(parentId);
197         }
198
199         BoneInfo nextBone = null;
200         if(tailId != 0){
201             nextBone = this.boneList.get(tailId);
202         }
203
204         BoneInfo srcBone = null;
205         if(this.currentBone.getBoneType() == BoneType.LINKEDROT){
206             srcBone = null;
207             int ratio = srcId;
208             this.currentBone.setRotationRatio(ratio);
209         }else if(0 < srcId && srcId < PmdLimits.MAX_BONE){
210             srcBone = this.boneList.get(srcId);
211         }
212
213         this.currentBone.setPrevBone(prevBone);
214         this.currentBone.setNextBone(nextBone);
215         this.currentBone.setSrcBone(srcBone);
216
217         return;
218     }
219
220     /**
221      * {@inheritDoc}
222      * @param xPos {@inheritDoc}
223      * @param yPos {@inheritDoc}
224      * @param zPos {@inheritDoc}
225      */
226     @Override
227     public void pmdBonePosition(float xPos, float yPos, float zPos){
228         MkPos3D position = this.currentBone.getPosition();
229         position.setXpos(xPos);
230         position.setYpos(yPos);
231         position.setZpos(zPos);
232         return;
233     }
234
235     /**
236      * {@inheritDoc}
237      * @param boneId {@inheritDoc}
238      * @param targetId {@inheritDoc}
239      * @param depth {@inheritDoc}
240      * @param weight {@inheritDoc}
241      */
242     @Override
243     public void pmdIKInfo(int boneId, int targetId, int depth, float weight){
244         BoneInfo bone = this.boneList.get(boneId);
245         this.currentIkChain.setIkBone(bone);
246
247         BoneInfo target = this.boneList.get(targetId);
248         this.currentIkChain.getChainedBoneList().add(0, target);
249
250         this.currentIkChain.setIKDepth(depth);
251         this.currentIkChain.setIKWeight(weight);
252
253         return;
254     }
255
256     /**
257      * {@inheritDoc}
258      * @param childId {@inheritDoc}
259      */
260     @Override
261     public void pmdIKChainInfo(int childId){
262         BoneInfo chain = this.boneList.get(childId);
263         this.currentIkChain.getChainedBoneList().add(chain);
264         return;
265     }
266
267     /**
268      * {@inheritDoc}
269      * @param groupName {@inheritDoc}
270      */
271     @Override
272     public void pmdBoneGroupInfo(String groupName){
273         this.currentBoneGroup.getGroupName().setPrimaryText(groupName);
274         return;
275     }
276
277     /**
278      * {@inheritDoc}
279      * @param boneId {@inheritDoc}
280      * @param groupId {@inheritDoc}
281      */
282     @Override
283     public void pmdGroupedBoneInfo(int boneId, int groupId){
284         BoneInfo bone = this.boneList.get(boneId);
285         BoneGroup group = this.boneGroupList.get(groupId);
286         group.getBoneList().add(bone);
287         return;
288     }
289
290 }