Physics On/Off menu is added.
Playback control interface is updated.
@@ -19,6 +19,9 @@ | ||
19 | 19 | import android.view.Menu; |
20 | 20 | import android.view.MenuItem; |
21 | 21 | import android.view.MotionEvent; |
22 | +import android.view.View; | |
23 | +import android.view.View.OnClickListener; | |
24 | +import android.widget.Button; | |
22 | 25 | import android.widget.RelativeLayout; |
23 | 26 | import android.widget.RelativeLayout.LayoutParams; |
24 | 27 | import android.widget.SeekBar; |
@@ -30,6 +33,8 @@ | ||
30 | 33 | private MMGLSurfaceView mMMGLSurfaceView; |
31 | 34 | private RelativeLayout mRelativeLayout; |
32 | 35 | private SeekBar mSeekBar; |
36 | + private Button mPlayPauseButton; | |
37 | + private Button mRewindButton; | |
33 | 38 | |
34 | 39 | // Model |
35 | 40 | private CoreLogic mCoreLogic; |
@@ -52,25 +57,6 @@ | ||
52 | 57 | mCoreLogic = new CoreLogic(this) { |
53 | 58 | @Override |
54 | 59 | public void onInitialize() { |
55 | - /* | |
56 | - try { | |
57 | - mCoreLogic.restoreState(); | |
58 | - final int max = mCoreLogic.getDulation(); | |
59 | - mSeekBar.post(new Runnable() { | |
60 | - @Override | |
61 | - public void run() { | |
62 | - mSeekBar.setMax(max); | |
63 | - } | |
64 | - }); | |
65 | - } catch (OutOfMemoryError e) { | |
66 | - MikuMikuDroid.this.runOnUiThread(new Runnable() { | |
67 | - @Override | |
68 | - public void run() { | |
69 | - Toast.makeText(MikuMikuDroid.this, "Out of Memory. Abort.", Toast.LENGTH_LONG).show(); | |
70 | - } | |
71 | - }); | |
72 | - } | |
73 | - */ | |
74 | 60 | MikuMikuDroid.this.runOnUiThread(new Runnable() { |
75 | 61 | @Override |
76 | 62 | public void run() { |
@@ -123,10 +109,12 @@ | ||
123 | 109 | mRelativeLayout = new RelativeLayout(this); |
124 | 110 | mRelativeLayout.setVerticalGravity(Gravity.BOTTOM); |
125 | 111 | mMMGLSurfaceView = new MMGLSurfaceView(this, mCoreLogic); |
112 | + | |
126 | 113 | LayoutParams p = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); |
127 | 114 | p.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); |
128 | 115 | mSeekBar = new SeekBar(this); |
129 | 116 | mSeekBar.setLayoutParams(p); |
117 | + mSeekBar.setId(1024); | |
130 | 118 | mSeekBar.setVisibility(SeekBar.INVISIBLE); |
131 | 119 | mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { |
132 | 120 | private boolean mIsPlaying = false; |
@@ -155,8 +143,47 @@ | ||
155 | 143 | } |
156 | 144 | |
157 | 145 | }); |
146 | + | |
147 | + p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); | |
148 | + p.addRule(RelativeLayout.CENTER_HORIZONTAL); | |
149 | + p.addRule(RelativeLayout.ABOVE, mSeekBar.getId()); | |
150 | + p.setMargins(5, 5, 5, 60); | |
151 | + mPlayPauseButton = new Button(this); | |
152 | + mPlayPauseButton.setLayoutParams(p); | |
153 | + mPlayPauseButton.setVisibility(Button.INVISIBLE); | |
154 | + mPlayPauseButton.setBackgroundResource(R.drawable.ic_media_play); | |
155 | + mPlayPauseButton.setId(mSeekBar.getId() + 1); | |
156 | + mPlayPauseButton.setOnClickListener(new OnClickListener() { | |
157 | + @Override | |
158 | + public void onClick(View v) { | |
159 | + if(mCoreLogic.toggleStartStop()) { | |
160 | + mPlayPauseButton.setBackgroundResource(R.drawable.ic_media_pause); | |
161 | + } else { | |
162 | + mPlayPauseButton.setBackgroundResource(R.drawable.ic_media_play); | |
163 | + } | |
164 | + } | |
165 | + }); | |
166 | + | |
167 | + p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); | |
168 | + p.addRule(RelativeLayout.ABOVE, mSeekBar.getId()); | |
169 | + p.addRule(RelativeLayout.LEFT_OF, mPlayPauseButton.getId()); | |
170 | + p.setMargins(5, 5, 60, 60); | |
171 | + mRewindButton = new Button(this); | |
172 | + mRewindButton.setLayoutParams(p); | |
173 | + mRewindButton.setVisibility(Button.INVISIBLE); | |
174 | + mRewindButton.setBackgroundResource(R.drawable.ic_media_previous); | |
175 | + mRewindButton.setOnClickListener(new OnClickListener() { | |
176 | + @Override | |
177 | + public void onClick(View v) { | |
178 | + mCoreLogic.rewind(); | |
179 | + } | |
180 | + }); | |
181 | + | |
182 | + | |
158 | 183 | mRelativeLayout.addView(mMMGLSurfaceView); |
159 | 184 | mRelativeLayout.addView(mSeekBar); |
185 | + mRelativeLayout.addView(mPlayPauseButton); | |
186 | + mRelativeLayout.addView(mRewindButton); | |
160 | 187 | setContentView(mRelativeLayout); |
161 | 188 | |
162 | 189 | if (mCoreLogic.checkFileIsPrepared() == false) { |
@@ -197,7 +224,7 @@ | ||
197 | 224 | menu.add(0, Menu.FIRST + 1, Menu.NONE, R.string.menu_load_camera); |
198 | 225 | menu.add(0, Menu.FIRST + 2, Menu.NONE, R.string.menu_load_music); |
199 | 226 | menu.add(0, Menu.FIRST + 3, Menu.NONE, R.string.menu_play_pause); |
200 | - menu.add(0, Menu.FIRST + 4, Menu.NONE, R.string.menu_rewind); | |
227 | + menu.add(0, Menu.FIRST + 4, Menu.NONE, R.string.menu_toggle_physics); | |
201 | 228 | menu.add(0, Menu.FIRST + 5, Menu.NONE, R.string.menu_initialize); |
202 | 229 | |
203 | 230 | return ret; |
@@ -360,7 +387,7 @@ | ||
360 | 387 | break; |
361 | 388 | |
362 | 389 | case (Menu.FIRST + 4): |
363 | - mCoreLogic.rewind(); | |
390 | + mCoreLogic.togglePhysics(); | |
364 | 391 | break; |
365 | 392 | |
366 | 393 | case (Menu.FIRST + 5): |
@@ -416,7 +443,15 @@ | ||
416 | 443 | @Override |
417 | 444 | public boolean onTouchEvent(MotionEvent event) { |
418 | 445 | if(event.getAction() == MotionEvent.ACTION_UP) { |
446 | + if(mCoreLogic.isPlaying()) { | |
447 | + mPlayPauseButton.setBackgroundResource(R.drawable.ic_media_pause); | |
448 | + } else { | |
449 | + mPlayPauseButton.setBackgroundResource(R.drawable.ic_media_play); | |
450 | + } | |
451 | + | |
419 | 452 | mSeekBar.setVisibility(mSeekBar.getVisibility() == SeekBar.VISIBLE ? SeekBar.INVISIBLE : SeekBar.VISIBLE); |
453 | + mPlayPauseButton.setVisibility(mPlayPauseButton.getVisibility() == Button.VISIBLE ? Button.INVISIBLE : Button.VISIBLE); | |
454 | + mRewindButton.setVisibility(mRewindButton.getVisibility() == Button.VISIBLE ? Button.INVISIBLE : Button.VISIBLE); | |
420 | 455 | mRelativeLayout.requestLayout(); |
421 | 456 | } |
422 | 457 | return false; |
@@ -106,12 +106,12 @@ | ||
106 | 106 | } |
107 | 107 | } |
108 | 108 | |
109 | - public void setBonePosByVMDFramePost() { | |
109 | + public void setBonePosByVMDFramePost(boolean physics) { | |
110 | 110 | ArrayList<Bone> ba = mModel.mBone; |
111 | 111 | if(ba != null) { |
112 | 112 | int max = ba.size(); |
113 | 113 | |
114 | - if(mIsArm) { | |
114 | + if(mIsArm && physics) { | |
115 | 115 | solvePhysicsPost(); |
116 | 116 | } |
117 | 117 | for (int r = 0; r < max; r++) { |
@@ -46,6 +46,7 @@ | ||
46 | 46 | private int mWidth; |
47 | 47 | private int mHeight; |
48 | 48 | private int mAngle; |
49 | + private boolean mPhysics = false; | |
49 | 50 | |
50 | 51 | // temporary data |
51 | 52 | private CameraIndex mCameraIndex = new CameraIndex(); |
@@ -71,7 +72,7 @@ | ||
71 | 72 | mMax = 0; |
72 | 73 | } |
73 | 74 | |
74 | - public void toggleStartStop() { | |
75 | + public boolean toggleStartStop() { | |
75 | 76 | updatePos(); |
76 | 77 | if(mIsPlaying) { // during play |
77 | 78 | stop(); |
@@ -78,6 +79,7 @@ | ||
78 | 79 | } else { |
79 | 80 | start(); |
80 | 81 | } |
82 | + return mIsPlaying; | |
81 | 83 | } |
82 | 84 | |
83 | 85 | public int getCurrentPosition() { |
@@ -216,7 +218,7 @@ | ||
216 | 218 | Miku miku = mMiku.get(mMiku.size() - 1); |
217 | 219 | miku.attachMotion(motion); |
218 | 220 | miku.setBonePosByVMDFramePre(0, 0, true); |
219 | - miku.setBonePosByVMDFramePost(); | |
221 | + miku.setBonePosByVMDFramePost(mPhysics); | |
220 | 222 | miku.setFaceByVMDFrame(0); |
221 | 223 | |
222 | 224 | // store IK chache |
@@ -270,7 +272,7 @@ | ||
270 | 272 | Miku miku = new Miku(model); |
271 | 273 | miku.attachMotion(motion); |
272 | 274 | miku.setBonePosByVMDFramePre(0, 0, true); |
273 | - miku.setBonePosByVMDFramePost(); | |
275 | + miku.setBonePosByVMDFramePost(mPhysics); | |
274 | 276 | miku.setFaceByVMDFrame(0); |
275 | 277 | miku.addRenderSenario("builtin:default", "screen"); |
276 | 278 | miku.addRenderSenario("builtin:default_alpha", "screen"); |
@@ -369,6 +371,10 @@ | ||
369 | 371 | public synchronized void loadCamera(String camera) throws IOException { |
370 | 372 | mCamera = new MikuMotion(new VMDParser(camera)); |
371 | 373 | } |
374 | + | |
375 | + public synchronized void togglePhysics() { | |
376 | + mPhysics = !mPhysics; | |
377 | + } | |
372 | 378 | |
373 | 379 | native private void btClearAllData(); |
374 | 380 |
@@ -441,7 +447,7 @@ | ||
441 | 447 | } |
442 | 448 | |
443 | 449 | // exec physics simulation |
444 | - if(isArm() && (step != 0 || !initializePhysics)) { | |
450 | + if(isArm() && mPhysics && (step != 0 || !initializePhysics)) { | |
445 | 451 | btStepSimulation(step, 5); |
446 | 452 | } |
447 | 453 |
@@ -448,7 +454,7 @@ | ||
448 | 454 | if (mMiku != null) { |
449 | 455 | for (Miku miku : mMiku) { |
450 | 456 | if(miku.hasMotion()) { |
451 | - miku.setBonePosByVMDFramePost(); | |
457 | + miku.setBonePosByVMDFramePost(mPhysics); | |
452 | 458 | } |
453 | 459 | } |
454 | 460 | } |
@@ -476,9 +482,8 @@ | ||
476 | 482 | return true; |
477 | 483 | } |
478 | 484 | } else { |
479 | - mFakeMedia.toggleStartStop(); | |
485 | + return mFakeMedia.toggleStartStop(); | |
480 | 486 | } |
481 | - return false; | |
482 | 487 | } |
483 | 488 | |
484 | 489 | public boolean isPlaying() { |
@@ -16,4 +16,5 @@ | ||
16 | 16 | |
17 | 17 | |
18 | 18 | |
19 | +<string name="menu_toggle_physics">Physics ON/OFF</string> | |
19 | 20 | </resources> |